Changeset 2dd650d


Ignore:
Timestamp:
Oct 1, 2009 6:18:23 PM (11 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
7094489
Parents:
3a1c042c (diff), 7e80379 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

propagate from branch 'i2p.i2p.zzz.test3' (head 459a56e53d8d694591071574e87474b5e95d6494)

to branch 'i2p.i2p' (head ffa1aab7aa8e75d75c183fd6f76140f7d840a6ae)

Files:
5 added
54 edited
2 moved

Legend:

Unmodified
Added
Removed
  • Slackware/i2p-base/i2p-base.SlackBuild

    r3a1c042c r2dd650d  
    2525NAME=i2p-base
    2626VERSION=0.0.1
    27 BUILD=1sim
     27BUILD=1sponge
    2828ARCH=noarch
    2929INSTALL_DIR=opt
     
    3939
    4040cd $PKG
    41 requiredbuilder -v -y -s $CWD $PKG
     41#
     42# Not really that important to exec this.
     43#requiredbuilder -v -y -s $CWD $PKG
     44#
     45cat $CWD/slack-required > $PKG/install/slack-required
    4246makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
  • Slackware/i2p/i2p.SlackBuild

    r3a1c042c r2dd650d  
    1616# For any additional information, visit i2host.i2p and forum.i2p
    1717
    18 BUILD=1sim
     18BUILD=1sponge
    1919
    2020# put here installation dir, without first and last /
     
    114114
    115115cd $PKG
    116 requiredbuilder -v -y -s $CWD $PKG
     116#
     117# requiredbuilder fucks up REALLY bad, and thinks java is perl?!
     118# It also did not catch the shell requirements! BOOOOOOOOOOO! HISSSSSSSS!
     119#
     120#requiredbuilder -v -y -s $CWD $PKG
     121#
     122cat $CWD/slack-required > $PKG/install/slack-required
    117123makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
  • Slackware/i2p/slack-required

    r3a1c042c r2dd650d  
    1 glibc >= 2.7-i486-17 | glibc-solibs >= 2.7-i486-17
    2 perl >= 5.10.0-i486-1
     1jre >= 5
     2i2p-base >= 0.0.1
     3bash >= 3.1.017
     4
  • apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java

    r3a1c042c r2dd650d  
    8686        out.write(HEADER);
    8787        out.write("</head><body>");
    88         out.write("<center><div class=\"page\">");
     88        out.write("<center>");
    8989        out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\"Refresh page\" class=\"snarkRefresh\">I2PSnark</a> <a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">Forum</a>\n");
    9090        Map trackers = _manager.getTrackers();
     
    9797                continue;
    9898            baseURL = baseURL.substring(e + 1);
    99             out.write("<a href=\"" + baseURL + "\" class=\"snarkRefresh\" target=\"_blank\">" + name + "</a>");
     99            out.write(" <a href=\"" + baseURL + "\" class=\"snarkRefresh\" target=\"_blank\">" + name + "</a>");
    100100        }
    101101        out.write("</div>\n");
    102         out.write("<div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
     102        out.write("<div class=\"page\"><div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
    103103        List msgs = _manager.getMessages();
    104104        for (int i = msgs.size()-1; i >= 0; i--) {
     
    499499        if (remaining == 0)
    500500            out.write("<a href=\"" + _manager.linkPrefix() + snark.meta.getName()
    501                       + "\" title=\"Click to access completed downloaded..\">");
     501                      + "\" title=\"View file\">");
    502502        out.write(filename);
    503503        if (remaining == 0)
     
    574574                out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">");
    575575                out.write("</td>\n\t");
    576                 out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">");
     576                out.write("<td align=\"left\" class=\"snarkTorrentStatus " + rowClass + "\">");
    577577                String ch = peer.toString().substring(0, 4);
    578578                String client;
     
    593593                else
    594594                    client = "Unknown (" + ch + ')';
    595                 out.write("<font size=-1>" + client + "</font>&nbsp;&nbsp;" + peer.toString().substring(5, 9) + "");
     595                out.write("" + client + "&nbsp;&nbsp;" + peer.toString().substring(5, 9) + "");
    596596                if (showDebug)
    597597                    out.write(" inactive " + (peer.getInactiveTime() / 1000) + "s");
     
    602602                float pct = (float) (100.0 * (float) peer.completed() / snark.meta.getPieces());
    603603                if (pct == 100.0)
    604                     out.write("<font size=-1>Seed</font>");
     604                    out.write("Seed");
    605605                else {
    606606                    String ps = String.valueOf(pct);
    607607                    if (ps.length() > 5)
    608608                        ps = ps.substring(0, 5);
    609                     out.write("<font size=-1>" + ps + "%</font>");
     609                    out.write("" + ps + "%");
    610610                }
    611611                out.write("</td>\n\t");
     
    616616                    if (peer.isInteresting() && !peer.isChoked()) {
    617617                        out.write("<font color=#008000>");
    618                         out.write("<font size=-1>" + formatSize(peer.getDownloadRate()) + "ps</font></font>");
     618                        out.write("" + formatSize(peer.getDownloadRate()) + "ps</font>");
    619619                    } else {
    620                         out.write("<font color=#a00000><font size=-1><a title=\"");
     620                        out.write("<font color=#a00000><a title=\"");
    621621                        if (!peer.isInteresting())
    622622                            out.write("Uninteresting\">");
    623623                        else
    624624                            out.write("Choked\">");
    625                         out.write(formatSize(peer.getDownloadRate()) + "ps</a></font></font>");
     625                        out.write(formatSize(peer.getDownloadRate()) + "ps</a></font>");
    626626                    }
    627627                }
     
    631631                    if (peer.isInterested() && !peer.isChoking()) {
    632632                        out.write("<font color=#008000>");
    633                         out.write("<font size=-1>" + formatSize(peer.getUploadRate()) + "ps</font></font>");
     633                        out.write("" + formatSize(peer.getUploadRate()) + "ps</font>");
    634634                    } else {
    635                         out.write("<font color=#a00000><font size=-1><a title=\"");
     635                        out.write("<font color=#a00000><a title=\"");
    636636                        if (!peer.isInterested())
    637637                            out.write("Uninterested\">");
    638638                        else
    639639                            out.write("Choking\">");
    640                         out.write(formatSize(peer.getUploadRate()) + "ps</a></font></font>");
     640                        out.write(formatSize(peer.getUploadRate()) + "ps</a></font>");
    641641                    }
    642642                }
  • apps/i2ptunnel/jsp/editClient.jsp

    r3a1c042c r2dd650d  
    1414<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    1515<head>
    16     <title>I2PTunnel Webmanager - Edit</title>
     16    <title>I2P Tunnel Manager - Edit</title>
    1717    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    1818    <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
  • apps/i2ptunnel/jsp/editServer.jsp

    r3a1c042c r2dd650d  
    1414<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    1515<head>
    16     <title>I2PTunnel Webmanager - Edit</title>
     16    <title>I2P Tunnel Manager - Edit</title>
    1717    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    1818    <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
  • apps/ministreaming/java/src/net/i2p/client/streaming/package.html

    r3a1c042c r2dd650d  
    1717appropriate {@link net.i2p.client.streaming.I2PSocketManager#connect} call.</p>
    1818
    19 <p>There is a simple pair of demo applications available as well - {@link
    20 net.i2p.client.streaming.StreamSinkServer} listens to a destination and dumps
    21 the data from all sockets it accepts to individual files, while {@link
    22 net.i2p.client.streaming.StreamSinkClient} connects to a particular destination
     19<p>There is a simple pair of demo applications available as well -
     20net.i2p.client.streaming.StreamSinkServer listens to a destination and dumps
     21the data from all sockets it accepts to individual files, while
     22net.i2p.client.streaming.StreamSinkClient connects to a particular destination
    2323and sends a specific amount of random data then disconnects.</p>
    2424</body></html>
  • apps/routerconsole/jsp/error.jsp

    r3a1c042c r2dd650d  
    1313    // If it can't find the iframe or viewtheme.jsp I wonder if the whole thing blows up...
    1414%>
    15 <html><head><title>I2P Router Console</title>
     15<html><head><title>I2P Router Console - Page Not Found</title>
    1616<%@include file="css.jsp" %>
    1717</head><body>
     
    2323<%@include file="summary.jsp" %>
    2424<h1><%=ERROR_CODE%> <%=ERROR_MESSAGE%></h1>
    25 <div class="warning" id="warning">
    26 The Router Console page <%=ERROR_URI%> was not found.
     25<div class="sorry" id="warning">
     26Sorry! You appear to be requesting a non-existent Router Console page or resource.<hr>
     27Error 404: <%=ERROR_URI%> not found.
    2728</div></body></html>
  • apps/routerconsole/jsp/help.jsp

    r3a1c042c r2dd650d  
    177177 <p>A more complete list of changes can be found
    178178 in the history.txt file in your i2p directory.
    179  </p><br></div></body></html>
     179 </p><hr></div></body></html>
  • apps/sam/java/src/net/i2p/sam/SAMHandler.java

    r3a1c042c r2dd650d  
    103103   
    104104    static public void writeBytes(ByteBuffer data, SocketChannel out) throws IOException {
    105         while (data.hasRemaining()) out.write(data);           
    106         out.socket().getOutputStream().flush();
     105        while (data.hasRemaining()) out.write(data);           
     106        out.socket().getOutputStream().flush();
    107107    }
    108108   
     
    125125     */
    126126    protected final boolean writeString(String str) {
    127         if (_log.shouldLog(Log.DEBUG))
    128             _log.debug("Sending the client: [" + str + "]");
    129         return writeString(str, socket);
     127        synchronized (socketWLock) {
     128            if (_log.shouldLog(Log.DEBUG))
     129                _log.debug("Sending the client: [" + str + "]");
     130            return writeString(str, socket);
     131        }
    130132    }
    131133
  • apps/streaming/java/src/net/i2p/client/streaming/Connection.java

    r3a1c042c r2dd650d  
    355355    }
    356356   
     357/*********
    357358    private class PingNotifier implements ConnectionManager.PingNotifier {
    358359        private long _startedPingOn;
     
    368369        }
    369370    }
     371*********/
    370372   
    371373    List ackPackets(long ackThrough, long nacks[]) {
     
    549551    }
    550552   
     553    /** ignore tag issues */
    551554    private void killOutstandingPackets() {
    552         boolean tagsCancelled = false;
     555        //boolean tagsCancelled = false;
    553556        synchronized (_outboundPackets) {
    554557            for (Iterator iter = _outboundPackets.values().iterator(); iter.hasNext(); ) {
    555558                PacketLocal pl = (PacketLocal)iter.next();
    556                 if ( (pl.getTagsSent() != null) && (pl.getTagsSent().size() > 0) )
    557                     tagsCancelled = true;
     559                //if ( (pl.getTagsSent() != null) && (pl.getTagsSent().size() > 0) )
     560                //    tagsCancelled = true;
    558561                pl.cancelled();
    559562            }
     
    561564            _outboundPackets.notifyAll();
    562565        }           
    563         if (tagsCancelled)
    564             _context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
     566        //if (tagsCancelled)
     567        //    _context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
    565568    }
    566569   
     
    11411144                // in case things really suck, the other side may have lost thier
    11421145                // session tags (e.g. they restarted), so jump back to ElGamal.
    1143                 int failTagsAt = _options.getMaxResends() - 2;
    1144                 if ( (newWindowSize == 1) && (numSends == failTagsAt) ) {
    1145                     if (_log.shouldLog(Log.WARN))
    1146                         _log.warn("Optimistically failing tags at resend " + numSends);
    1147                     _context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
    1148                 }
     1146                //int failTagsAt = _options.getMaxResends() - 2;
     1147                //if ( (newWindowSize == 1) && (numSends == failTagsAt) ) {
     1148                //    if (_log.shouldLog(Log.WARN))
     1149                //        _log.warn("Optimistically failing tags at resend " + numSends);
     1150                //    _context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
     1151                //}
    11491152               
    11501153                if (numSends - 1 > _options.getMaxResends()) {
  • apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java

    r3a1c042c r2dd650d  
    350350        }
    351351    }
     352
     353    /** blocking */
    352354    public boolean ping(Destination peer, long timeoutMs) {
    353         return ping(peer, timeoutMs, true);
     355        return ping(peer, timeoutMs, true, null);
    354356    }
    355357    public boolean ping(Destination peer, long timeoutMs, boolean blocking) {
    356         return ping(peer, timeoutMs, blocking, null, null, null);
    357     }
    358 
     358        return ping(peer, timeoutMs, blocking, null);
     359    }
     360
     361    /**
     362     * @deprecated I2PSession ignores tags, use non-tag variant
     363     * @param keyToUse ignored
     364     * @param tagsToSend ignored
     365     */
    359366    public boolean ping(Destination peer, long timeoutMs, boolean blocking, SessionKey keyToUse, Set tagsToSend, PingNotifier notifier) {
     367        return ping(peer, timeoutMs, blocking, notifier);
     368    }
     369
     370    public boolean ping(Destination peer, long timeoutMs, boolean blocking, PingNotifier notifier) {
    360371        Long id = new Long(_context.random().nextLong(Packet.MAX_STREAM_ID-1)+1);
    361372        PacketLocal packet = new PacketLocal(_context, peer);
     
    364375        packet.setFlag(Packet.FLAG_SIGNATURE_INCLUDED);
    365376        packet.setOptionalFrom(_session.getMyDestination());
    366         if ( (keyToUse != null) && (tagsToSend != null) ) {
    367             packet.setKeyUsed(keyToUse);
    368             packet.setTagsSent(tagsToSend);
    369         }
     377        //if ( (keyToUse != null) && (tagsToSend != null) ) {
     378        //    packet.setKeyUsed(keyToUse);
     379        //    packet.setTagsSent(tagsToSend);
     380        //}
    370381       
    371382        PingRequest req = new PingRequest(peer, packet, notifier);
     
    436447        public void pong() {
    437448            _log.debug("Ping successful");
    438             _context.sessionKeyManager().tagsDelivered(_peer.getPublicKey(), _packet.getKeyUsed(), _packet.getTagsSent());
     449            //_context.sessionKeyManager().tagsDelivered(_peer.getPublicKey(), _packet.getKeyUsed(), _packet.getTagsSent());
    439450            synchronized (ConnectionManager.PingRequest.this) {
    440451                _ponged = true;
  • apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java

    r3a1c042c r2dd650d  
    264264               
    265265                // ACK the tags we delivered so we can use them
    266                 if ( (p.getKeyUsed() != null) && (p.getTagsSent() != null)
    267                       && (p.getTagsSent().size() > 0) ) {
    268                     _context.sessionKeyManager().tagsDelivered(p.getTo().getPublicKey(),
    269                                                                p.getKeyUsed(),
    270                                                                p.getTagsSent());
    271                 }
     266                //if ( (p.getKeyUsed() != null) && (p.getTagsSent() != null)
     267                //      && (p.getTagsSent().size() > 0) ) {
     268                //    _context.sessionKeyManager().tagsDelivered(p.getTo().getPublicKey(),
     269                //                                               p.getKeyUsed(),
     270                //                                               p.getTagsSent());
     271                //}
    272272                if (_log.shouldLog(Log.DEBUG))
    273273                    _log.debug("Packet acked after " + p.getAckTime() + "ms: " + p);
  • apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java

    r3a1c042c r2dd650d  
    4848    public void setTo(Destination to) { _to = to; }
    4949   
     50    /**
     51     * @deprecated should always return null
     52     */
    5053    public SessionKey getKeyUsed() { return _keyUsed; }
    51     public void setKeyUsed(SessionKey key) { _keyUsed = key; }
    52    
     54
     55    /**
     56     * @deprecated I2PSession throws out the tags
     57     */
     58    public void setKeyUsed(SessionKey key) {
     59        if (key != null)
     60            _log.error("Who is sending tags thru the streaming lib?");
     61        _keyUsed = key;
     62    }
     63   
     64    /**
     65     * @deprecated should always return null or an empty set
     66     */
    5367    public Set getTagsSent() { return _tagsSent; }
     68
     69    /**
     70     * @deprecated I2PSession throws out the tags
     71     */
    5472    public void setTagsSent(Set tags) {
     73        if (tags != null && tags.size() > 0)
     74            _log.error("Who is sending tags thru the streaming lib? " + tags.size());
    5575        if ( (_tagsSent != null) && (_tagsSent.size() > 0) && (tags.size() > 0) ) {
    5676            //int old = _tagsSent.size();
  • apps/streaming/java/src/net/i2p/client/streaming/PacketQueue.java

    r3a1c042c r2dd650d  
    3737    /**
    3838     * Add a new packet to be sent out ASAP
     39     *
     40     * keys and tags disabled since dropped in I2PSession
    3941     */
    4042    public void enqueue(PacketLocal packet) {
    4143        packet.prepare();
    4244       
    43         SessionKey keyUsed = packet.getKeyUsed();
    44         if (keyUsed == null)
    45             keyUsed = new SessionKey();
    46         Set tagsSent = packet.getTagsSent();
    47         if (tagsSent == null)
    48             tagsSent = new HashSet(0);
     45        //SessionKey keyUsed = packet.getKeyUsed();
     46        //if (keyUsed == null)
     47        //    keyUsed = new SessionKey();
     48        //Set tagsSent = packet.getTagsSent();
     49        //if (tagsSent == null)
     50        //    tagsSent = new HashSet(0);
    4951
    5052        // cache this from before sendMessage
     
    9395                //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires);
    9496                // I2PSessionMuxedImpl
    95                 sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires,
     97                //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires,
     98                //                 I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
     99                // I2PSessionMuxedImpl no tags
     100                sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null, expires,
    96101                                 I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
    97102            else
     
    99104                //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, 0);
    100105                // I2PSessionMuxedImpl
    101                 sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent,
     106                //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent,
     107                //                 I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
     108                // I2PSessionMuxedImpl no tags
     109                sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null,
    102110                                 I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
    103111            end = _context.clock().now();
     
    130138                c.disconnect(false);
    131139        } else {
    132             packet.setKeyUsed(keyUsed);
    133             packet.setTagsSent(tagsSent);
     140            //packet.setKeyUsed(keyUsed);
     141            //packet.setTagsSent(tagsSent);
    134142            packet.incrementSends();
    135143            if (_log.shouldLog(Log.DEBUG)) {
    136                 String msg = "SEND " + packet + (tagsSent.size() > 0
    137                              ? " with " + tagsSent.size() + " tags"
    138                              : "")
     144                String msg = "SEND " + packet
    139145                             + " send # " + packet.getNumSends()
    140146                             + " sendTime: " + (end-begin)
  • checklist.txt

    r3a1c042c r2dd650d  
    7474        Sync with mtn.i2p2.i2p
    7575
    76 Announce on #i2p, forum.i2p
     76Announce on #i2p, forum.i2p, freshmeat.net, launchpad.net
  • core/c/jbigi/build.sh

    r3a1c042c r2dd650d  
    1616mkdir -p lib/
    1717mkdir -p bin/local
    18 VER=4.2.4
     18VER=4.3.1
    1919
    2020if [ "$1" != "dynamic" -a ! -d gmp-$VER ]
    2121then
    22         TAR=gmp-$VER.tar.bz2
     22        TAR=gmp-$VER.tar.lzma
    2323        if [ ! -f $TAR ]
    2424        then
    25                 echo "GMP tarball $TAR not found. You must download it from http://gmplib.org/"
    26                 exit 1
     25            echo "Downloading ftp://ftp.gmplib.org/pub/gmp-4.3.1/gmp-4.3.1.tar.lzma"
     26            wget ftp://ftp.gmplib.org/pub/gmp-4.3.1/gmp-4.3.1.tar.lzma
    2727        fi
    2828
     
    3030
    3131        echo "Extracting GMP..."
    32         tar -xjf gmp-$VER.tar.bz2
     32        tar -xf gmp-$VER.tar.lzma --lzma
    3333fi
    3434
     
    4343                        ../../gmp-$VER/configure --with-pic;;
    4444                *)
    45                         ../../gmp-$VER/configure;;
     45                        ../../gmp-$VER/configure --with-pic;;
    4646        esac
    4747        make
     
    5555cd ../..
    5656
    57 I2P=~/i2p
     57I2P=~/i2p/i2p
    5858if [ ! -f $I2P/lib/i2p.jar ]
    5959then
  • core/c/jcpuid/build.sh

    r3a1c042c r2dd650d  
    3838        COMPILEFLAGS="-fPIC -Wall"
    3939        INCLUDES="-I. -Iinclude -I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
    40         LINKFLAGS="-shared -static -static-libgcc -Wl,-soname,libjcpuid-x86-linux.so"
     40        LINKFLAGS="-shared -Wl,-soname,libjcpuid-x86-linux.so"
    4141        LIBFILE="lib/freenet/support/CPUInformation/libjcpuid-x86-linux.so";;
    4242esac
     
    4444echo "Compiling C code..."
    4545rm -f $LIBFILE
    46 $CC $LINKFLAGS $INCLUDES src/*.c -o $LIBFILE
     46$CC $COMPILEFLAGS $LINKFLAGS $INCLUDES src/*.c -o $LIBFILE
    4747strip $LIBFILE
    4848echo Built $LIBFILE
  • core/java/src/net/i2p/I2PAppContext.java

    r3a1c042c r2dd650d  
    389389     * data.  This component allows transparent operation of the
    390390     * ElGamal/AES+SessionTag algorithm, and contains all of the session tags
    391      * for one particular application.  If you want to seperate multiple apps
    392      * to have their own sessionTags and sessionKeys, they should use different
    393      * I2PAppContexts, and hence, different sessionKeyManagers.
     391     * for one particular application.
     392     *
     393     * This is deprecated for client use, it should be used only by the router
     394     * as its own key manager. Not that clients are doing end-to-end crypto anyway.
     395     *
     396     * For client crypto within the router,
     397     * use RouterContext.clientManager.getClientSessionKeyManager(dest)
    394398     *
    395399     */
  • core/java/src/net/i2p/client/I2CPMessageProducer.java

    r3a1c042c r2dd650d  
    9494     * Package up and send the payload to the router for delivery
    9595     *
     96     * @param tag unused - no end-to-end crypto
     97     * @param tags unused - no end-to-end crypto
     98     * @param key unused - no end-to-end crypto
     99     * @param newKey unused - no end-to-end crypto
    96100     */
    97101    public void sendMessage(I2PSessionImpl session, Destination dest, long nonce, byte[] payload, SessionTag tag,
     
    136140     * Create a new signed payload and send it off to the destination
    137141     *
     142     * @param tag unused - no end-to-end crypto
     143     * @param tags unused - no end-to-end crypto
     144     * @param key unused - no end-to-end crypto
     145     * @param newKey unused - no end-to-end crypto
    138146     */
    139147    private Payload createPayload(Destination dest, byte[] payload, SessionTag tag, SessionKey key, Set tags,
  • core/java/src/net/i2p/client/I2PSessionImpl.java

    r3a1c042c r2dd650d  
    362362    public abstract boolean sendMessage(Destination dest, byte[] payload) throws I2PSessionException;
    363363   
     364    /**
     365     * @param keyUsed unused - no end-to-end crypto
     366     * @param tagsSent unused - no end-to-end crypto
     367     */
    364368    public abstract boolean sendMessage(Destination dest, byte[] payload, SessionKey keyUsed,
    365369                                        Set tagsSent) throws I2PSessionException;
     
    367371    public abstract void receiveStatus(int msgId, long nonce, int status);
    368372
     373/****** no end-to-end crypto
    369374    protected static final Set createNewTags(int num) {
    370375        Set tags = new HashSet();
     
    373378        return tags;
    374379    }
     380*******/
    375381
    376382    /**
  • core/java/src/net/i2p/client/I2PSessionImpl2.java

    r3a1c042c r2dd650d  
    136136    }
    137137   
     138    /**
     139     * @param keyUsed unused - no end-to-end crypto
     140     * @param tagsSent unused - no end-to-end crypto
     141     */
    138142    @Override
    139143    public boolean sendMessage(Destination dest, byte[] payload, SessionKey keyUsed, Set tagsSent) throws I2PSessionException {
    140144        return sendMessage(dest, payload, 0, payload.length, keyUsed, tagsSent, 0);
    141145    }
     146
     147    /**
     148     * @param keyUsed unused - no end-to-end crypto
     149     * @param tagsSent unused - no end-to-end crypto
     150     */
    142151    public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent)
    143152                   throws I2PSessionException {
    144153        return sendMessage(dest, payload, offset, size, keyUsed, tagsSent, 0);
    145154    }
     155
     156    /**
     157     * @param keyUsed unused - no end-to-end crypto
     158     * @param tagsSent unused - no end-to-end crypto
     159     */
    146160    public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, long expires)
    147161                   throws I2PSessionException {
     
    199213    private static final int NUM_TAGS = 50;
    200214
     215    /**
     216     * @param keyUsed unused - no end-to-end crypto
     217     * @param tagsSent unused - no end-to-end crypto
     218     */
    201219    protected boolean sendBestEffort(Destination dest, byte payload[], SessionKey keyUsed, Set tagsSent, long expires)
    202220                    throws I2PSessionException {
    203         SessionKey key = null;
    204         SessionKey newKey = null;
    205         SessionTag tag = null;
    206         Set sentTags = null;
    207         int oldTags = 0;
     221        //SessionKey key = null;
     222        //SessionKey newKey = null;
     223        //SessionTag tag = null;
     224        //Set sentTags = null;
     225        //int oldTags = 0;
    208226        long begin = _context.clock().now();
    209227        /***********
     
    259277        if (_log.shouldLog(Log.DEBUG)) _log.debug("before sync state");
    260278        MessageState state = new MessageState(_context, nonce, getPrefix());
    261         state.setKey(key);
    262         state.setTags(sentTags);
    263         state.setNewKey(newKey);
     279        //state.setKey(key);
     280        //state.setTags(sentTags);
     281        //state.setNewKey(newKey);
    264282        state.setTo(dest);
    265         if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Setting key = " + key);
    266 
    267         if (keyUsed != null) {
     283        //if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Setting key = " + key);
     284
     285        //if (keyUsed != null) {
    268286            //if (I2CPMessageProducer.END_TO_END_CRYPTO) {
    269287            //    if (newKey != null)
     
    272290            //        keyUsed.setData(key.getData());
    273291            //} else {
    274                 keyUsed.setData(SessionKey.INVALID_KEY.getData());
     292            //    keyUsed.setData(SessionKey.INVALID_KEY.getData());
    275293            //}
    276         }
    277         if (tagsSent != null) {
    278             if (sentTags != null) {
    279                 tagsSent.addAll(sentTags);
    280             }
    281         }
     294        //}
     295        //if (tagsSent != null) {
     296        //    if (sentTags != null) {
     297        //        tagsSent.addAll(sentTags);
     298        //    }
     299        //}
    282300
    283301        if (_log.shouldLog(Log.DEBUG)) _log.debug("before sync state");
     
    294312                       + " sync took " + (inSendingSync-beforeSendingSync)
    295313                       + " add took " + (afterSendingSync-inSendingSync));
    296         _producer.sendMessage(this, dest, nonce, payload, tag, key, sentTags, newKey, expires);
     314        //_producer.sendMessage(this, dest, nonce, payload, tag, key, sentTags, newKey, expires);
     315        _producer.sendMessage(this, dest, nonce, payload, null, null, null, null, expires);
    297316       
    298317        // since this is 'best effort', all we're waiting for is a status update
  • core/java/src/net/i2p/client/I2PSessionMuxedImpl.java

    r3a1c042c r2dd650d  
    129129    }
    130130
     131    /**
     132     * @param keyUsed unused - no end-to-end crypto
     133     * @param tagsSent unused - no end-to-end crypto
     134     */
    131135    @Override
    132136    public boolean sendMessage(Destination dest, byte[] payload, int offset, int size,
     
    136140    }
    137141
     142    /**
     143     * @param keyUsed unused - no end-to-end crypto
     144     * @param tagsSent unused - no end-to-end crypto
     145     */
    138146    @Override
    139147    public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent,
     
    143151
    144152    /**
     153     *  @param keyUsed unused - no end-to-end crypto
     154     *  @param tagsSent unused - no end-to-end crypto
    145155     *  @param proto 1-254 or 0 for unset; recommended:
    146156     *         I2PSession.PROTO_UNSPECIFIED
  • core/java/src/net/i2p/client/MessagePayloadMessageHandler.java

    r3a1c042c r2dd650d  
    2222 * of a message by accepting it, decrypting the payload, adding it to the set of
    2323 * recieved messages, and telling the router that it has been recieved correctly.
     24 *
     25 * We don't really decrypt (no more end-to-end crypto)
    2426 *
    2527 * @author jrandom
     
    5254    /**
    5355     * Decrypt the payload
     56     *
     57     * We don't really decrypt (no more end-to-end crypto)
     58     * If we do, we need to use the correct key manager in the decrypt() call below
    5459     */
    5560    private Payload decryptPayload(MessagePayloadMessage msg, I2PSessionImpl session) throws DataFormatException {
    5661        Payload payload = msg.getPayload();
    57         if (!I2CPMessageProducer.END_TO_END_CRYPTO) {
     62        //if (!I2CPMessageProducer.END_TO_END_CRYPTO) {
    5863            payload.setUnencryptedData(payload.getEncryptedData());
    5964            return payload;
    60         }
     65        //}
    6166           
    62         byte[] data = _context.elGamalAESEngine().decrypt(payload.getEncryptedData(), session.getDecryptionKey());
    63         if (data == null) {
    64             if (_log.shouldLog(Log.WARN))
    65                 _log.warn("Error decrypting the payload");
    66             throw new DataFormatException("Unable to decrypt the payload");
    67         }
    68         payload.setUnencryptedData(data);
    69         return payload;
     67        //byte[] data = _context.elGamalAESEngine().decrypt(payload.getEncryptedData(), session.getDecryptionKey());
     68        //if (data == null) {
     69        //    if (_log.shouldLog(Log.WARN))
     70        //        _log.warn("Error decrypting the payload");
     71        //    throw new DataFormatException("Unable to decrypt the payload");
     72        //}
     73        //payload.setUnencryptedData(data);
     74        //return payload;
    7075    }
    7176}
  • core/java/src/net/i2p/crypto/ElGamalAESEngine.java

    r3a1c042c r2dd650d  
    6060
    6161    /**
    62      * Decrypt the message using the given private key using tags from the given key manager.
     62     * Decrypt the message using the given private key using tags from the default key manager.
     63     *
     64     * @deprecated specify the key manager!
    6365     */
    6466    public byte[] decrypt(byte data[], PrivateKey targetPrivateKey) throws DataFormatException {
     
    6769
    6870    /**
    69      * Decrypt the message using the given private key.  This works according to the
     71     * Decrypt the message using the given private key
     72     * and using tags from the specified key manager.
     73     * This works according to the
    7074     * ElGamal+AES algorithm in the data structure spec.
    7175     *
  • core/java/src/net/i2p/crypto/HMAC256Generator.java

    r3a1c042c r2dd650d  
    1313/**
    1414 * Calculate the HMAC-SHA256 of a key+message.  All the good stuff occurs
    15  * in {@link org.bouncycastle.crypto.macs.HMac} and
     15 * in {@link org.bouncycastle.crypto.macs.I2PHMac} and
    1616 * {@link org.bouncycastle.crypto.digests.MD5Digest}.
    1717 *
  • core/java/src/net/i2p/crypto/HMACGenerator.java

    r3a1c042c r2dd650d  
    1616/**
    1717 * Calculate the HMAC-MD5 of a key+message.  All the good stuff occurs
    18  * in {@link org.bouncycastle.crypto.macs.HMac} and
     18 * in {@link org.bouncycastle.crypto.macs.I2PHMac} and
    1919 * {@link org.bouncycastle.crypto.digests.MD5Digest}.
    2020 *
  • core/java/src/net/i2p/crypto/SessionKeyManager.java

    r3a1c042c r2dd650d  
    1010 */
    1111
     12import java.io.IOException;
     13import java.io.Writer;
    1214import java.util.Set;
    1315
     
    9496     *
    9597     */
    96     public void tagsDelivered(PublicKey target, SessionKey key, Set<SessionTag> sessionTags) { // nop
     98    public TagSetHandle tagsDelivered(PublicKey target, SessionKey key, Set<SessionTag> sessionTags) { // nop
     99         return null;
    97100    }
    98101
     
    131134    public void shutdown() { // nop
    132135    }
     136
     137    public void renderStatusHTML(Writer out) throws IOException {}
     138    public void failTags(PublicKey target, SessionKey key, TagSetHandle ts) {}
     139    public void tagsAcked(PublicKey target, SessionKey key, TagSetHandle ts) {}
    133140}
  • core/java/src/net/i2p/crypto/TransientSessionKeyManager.java

    r3a1c042c r2dd650d  
    1010 */
    1111
     12import java.io.IOException;
     13import java.io.Writer;
    1214import java.util.ArrayList;
     15import java.util.Comparator;
    1316import java.util.Date;
    1417import java.util.HashMap;
     
    1720import java.util.List;
    1821import java.util.Map;
     22import java.util.NoSuchElementException;
    1923import java.util.Set;
     24import java.util.TreeSet;
    2025
    2126import net.i2p.I2PAppContext;
     
    3237 * to disk).  However, this being java, we cannot guarantee that the keys aren't swapped
    3338 * out to disk so this should not be considered secure in that sense.
     39 *
     40 * The outbound and inbound sides are completely independent, each with
     41 * their own keys and tags.
     42 *
     43 * For a new session, outbound tags are not considered delivered until an ack is received.
     44 * Otherwise, the loss of the first message would render all subsequent messages
     45 * undecryptable. True?
     46 *
     47 * For an existing session, outbound tags are immediately considered delivered, and are
     48 * later revoked if the ack times out. This prevents massive stream slowdown caused by
     49 * repeated tag delivery after the minimum tag threshold is reached. Included tags
     50 * pushes messages above the ideal 1956 size by ~2KB and causes excessive fragmentation
     51 * and padding. As the tags are not seen by the streaming lib, they aren't accounted
     52 * for in the window size, and one or more of a series of large messages is likely to be dropped,
     53 * either due to high fragmentation or drop priorites at the tunnel OBEP.
     54 *
     55 * For this to work, the minimum tag threshold and tag delivery quanitity defined in
     56 * GarlicMessageBuilder must be chosen with streaming lib windows sizes in mind.
     57 * If a single TagSet is not delivered, there will be no stall as long as the
     58 * current window size is smaller than the minimum tag threshold.
     59 * Additional TagSets will be sent before the acked tags completely run out. See below.
     60 * all subsequent messages will fail to decrypt.
     61 * See ConnectionOptions in streaming for more information.
     62 *
     63 * There are large inefficiencies caused by the repeated delivery of tags in a new session.
     64 * With an initial streaming window size of 6 and 40 tags per delivery, a web server
     65 * would deliver up to 240 tags (7680 bytes, not including bundled leaseset, etc.)
     66 * in the first volley of the response.
     67 *
     68 * Could the two directions be linked somehow, such that the initial request could
     69 * contain a key or tags for the response?
     70 *
     71 * Should the tag threshold and quantity be adaptive?
     72 *
     73 * Todo: Switch to ConcurrentHashMaps and ReadWriteLocks, only get write lock during cleanup
    3474 *
    3575 */
     
    123163
    124164    /* FIXME Exporting non-public type through public API */
     165/****** leftover from when we had the persistent SKM
    125166    protected void setData(Set<TagSet> inboundTagSets, Set<OutboundSession> outboundSessions) {
    126167        if (_log.shouldLog(Log.INFO))
     
    149190        }
    150191    }
     192******/
    151193
    152194    /**
     
    176218     * when to expire that key begin with this call.
    177219     *
    178      * Unused except in tests?
    179220     */
    180221    @Override
    181222    public void createSession(PublicKey target, SessionKey key) {
    182         OutboundSession sess = new OutboundSession(target);
    183         sess.setCurrentKey(key);
    184         addSession(sess);
     223        createAndReturnSession(target, key);
    185224    }
    186225
     
    215254            SessionTag nxt = sess.consumeNext();
    216255            if (_log.shouldLog(Log.DEBUG))
    217                 _log.debug("Tag consumed: " + nxt + " with key: " + key.toBase64());
     256                _log.debug("OB Tag consumed: " + nxt + " with: " + key);
    218257            return nxt;
    219258        }
     
    258297    /**
    259298     * Take note of the fact that the given sessionTags associated with the key for
    260      * encryption to the target have definitely been received at the target (aka call this
    261      * method after receiving an ack to a message delivering them)
    262      *
    263      */
    264     @Override
    265     public void tagsDelivered(PublicKey target, SessionKey key, Set sessionTags) {
     299     * encryption to the target have been sent. Whether to use the tags immediately
     300     * (i.e. assume they will be received) or to wait until an ack, is implementation dependent.
     301     *
     302     * Here, we wait for the ack if the session is new, otherwise we use right away.
     303     * Will this work???
     304     * If the tags are pipelined sufficiently, it will.
     305     *
     306     * @return the TagSetHandle. Caller MUST subsequently call failTags() or tagsAcked()
     307     * with this handle.
     308     */
     309    @Override
     310    public TagSetHandle tagsDelivered(PublicKey target, SessionKey key, Set<SessionTag> sessionTags) {
    266311        if (_log.shouldLog(Log.DEBUG)) {
    267312            //_log.debug("Tags delivered to set " + set + " on session " + sess);
    268313            if (sessionTags.size() > 0)
    269                 _log.debug("Tags delivered: " + sessionTags.size() + " for key: " + key.toBase64() + ": " + sessionTags);
     314                _log.debug("Tags delivered: " + sessionTags.size() + " for key: " + key + ": " + sessionTags);
    270315        }
    271316        OutboundSession sess = getSession(target);
    272317        if (sess == null)
    273318            sess = createAndReturnSession(target, key);
    274         sess.setCurrentKey(key);
     319        else
     320            sess.setCurrentKey(key);
    275321        TagSet set = new TagSet(sessionTags, key, _context.clock().now());
    276322        sess.addTags(set);
     323        return set;
    277324    }
    278325
     
    282329     * from corrupted tag sets and crashes
    283330     *
     331     * @deprecated unused and rather drastic
    284332     */
    285333    @Override
    286334    public void failTags(PublicKey target) {
    287335        removeSession(target);
     336    }
     337
     338    /**
     339     * Mark these tags as invalid, since the peer
     340     * has failed to ack them in time.
     341     */
     342    @Override
     343    public void failTags(PublicKey target, SessionKey key, TagSetHandle ts) {
     344        OutboundSession sess = getSession(target);
     345        if (sess == null)
     346            return;
     347        if(!key.equals(sess.getCurrentKey()))
     348            return;
     349        sess.failTags((TagSet)ts);
     350        if (_log.shouldLog(Log.DEBUG))
     351            _log.debug("TagSet failed: " + ts);
     352    }
     353
     354    /**
     355     * Mark these tags as acked, start to use them (if we haven't already)
     356     */
     357    @Override
     358    public void tagsAcked(PublicKey target, SessionKey key, TagSetHandle ts) {
     359        OutboundSession sess = getSession(target);
     360        if (sess == null)
     361            return;
     362        if(!key.equals(sess.getCurrentKey()))
     363            return;
     364        sess.ackTags((TagSet)ts);
     365        if (_log.shouldLog(Log.DEBUG))
     366            _log.debug("TagSet acked: " + ts);
    288367    }
    289368
     
    301380            SessionTag tag = iter.next();
    302381            if (_log.shouldLog(Log.DEBUG))
    303                 _log.debug("Receiving tag " + tag + " for key " + key.toBase64() + " / " + key.toString() + ": tagSet: " + tagSet);
     382                _log.debug("Receiving tag " + tag + " for key " + key + ": tagSet: " + tagSet);
    304383            synchronized (_inboundTagSets) {
    305                 old = (TagSet)_inboundTagSets.put(tag, tagSet);
     384                old = _inboundTagSets.put(tag, tagSet);
    306385                overage = _inboundTagSets.size() - MAX_INBOUND_SESSION_TAGS;
    307386                if (old != null) {
     
    331410
    332411            if (_log.shouldLog(Log.WARN)) {
    333                 _log.warn("Multiple tags matching!  tagSet: " + tagSet + " and old tagSet: " + old + " tag: " + dupTag + "/" + dupTag.toBase64());
    334                 _log.warn("Earlier tag set creation: " + old + ": key=" + old.getAssociatedKey().toBase64(), old.getCreatedBy());
    335                 _log.warn("Current tag set creation: " + tagSet + ": key=" + tagSet.getAssociatedKey().toBase64(), tagSet.getCreatedBy());
     412                _log.warn("Multiple tags matching!  tagSet: " + tagSet + " and old tagSet: " + old + " tag: " + dupTag + "/" + dupTag);
     413                _log.warn("Earlier tag set creation: " + old + ": key=" + old.getAssociatedKey());
     414                _log.warn("Current tag set creation: " + tagSet + ": key=" + tagSet.getAssociatedKey());
    336415            }
    337416        }
     
    342421        if ( (sessionTags.size() <= 0) && (_log.shouldLog(Log.DEBUG)) )
    343422            _log.debug("Received 0 tags for key " + key);
    344         if (false) aggressiveExpire();
     423        //if (false) aggressiveExpire();
    345424    }
    346425   
     
    407486    @Override
    408487    public SessionKey consumeTag(SessionTag tag) {
    409         if (false) aggressiveExpire();
     488        //if (false) aggressiveExpire();
    410489        synchronized (_inboundTagSets) {
    411490            TagSet tagSet = (TagSet) _inboundTagSets.remove(tag);
    412491            if (tagSet == null) {
    413492                if (_log.shouldLog(Log.DEBUG))
    414                     _log.debug("Cannot consume tag " + tag + " as it is not known");
     493                    _log.debug("Cannot consume IB " + tag + " as it is not known");
    415494                return null;
    416495            }
     
    419498            SessionKey key = tagSet.getAssociatedKey();
    420499            if (_log.shouldLog(Log.DEBUG))
    421                 _log.debug("Consuming tag " + tag.toString() + " for sessionKey " + key.toBase64() + " / " + key.toString() + " on tagSet: " + tagSet);
     500                _log.debug("Consuming IB " + tag + " for " + key + " on: " + tagSet);
    422501            return key;
    423502        }
     
    426505    private OutboundSession getSession(PublicKey target) {
    427506        synchronized (_outboundSessions) {
    428             return (OutboundSession) _outboundSessions.get(target);
     507            return _outboundSessions.get(target);
    429508        }
    430509    }
     
    440519        OutboundSession session = null;
    441520        synchronized (_outboundSessions) {
    442             session = (OutboundSession)_outboundSessions.remove(target);
     521            session = _outboundSessions.remove(target);
    443522        }
    444523        if ( (session != null) && (_log.shouldLog(Log.WARN)) )
     
    458537        long now = _context.clock().now();
    459538        StringBuilder buf = null;
    460         StringBuilder bufSummary = null;
     539        //StringBuilder bufSummary = null;
    461540        if (_log.shouldLog(Log.DEBUG)) {
    462541            buf = new StringBuilder(128);
    463542            buf.append("Expiring inbound: ");
    464             bufSummary = new StringBuilder(1024);
     543            //bufSummary = new StringBuilder(1024);
    465544        }
    466545        synchronized (_inboundTagSets) {
     
    474553                    removed++;
    475554                    if (buf != null)
    476                         buf.append(tag.toString()).append(" @ age ").append(DataHelper.formatDuration(age));
    477                 } else if (false && (bufSummary != null) ) {
    478                     bufSummary.append("\nTagSet: " + ts.toString() + ", key: " + ts.getAssociatedKey().toBase64()+"/" + ts.getAssociatedKey().toString()
    479                                       + ": tag: " + tag.toString());
     555                        buf.append(tag).append(" @ age ").append(DataHelper.formatDuration(age));
     556                //} else if (false && (bufSummary != null) ) {
     557                //    bufSummary.append("\nTagSet: " + ts + ", key: " + ts.getAssociatedKey()
     558                //                      + ": tag: " + tag);
    480559                }
    481560            }
     
    485564        if ( (buf != null) && (removed > 0) )
    486565            _log.debug(buf.toString());
    487         if (bufSummary != null)
    488             _log.debug("Cleaning up with remaining: " + bufSummary.toString());
     566        //if (bufSummary != null)
     567        //    _log.debug("Cleaning up with remaining: " + bufSummary.toString());
    489568
    490569        //_log.warn("Expiring tags: [" + tagsToDrop + "]");
     
    495574                OutboundSession sess = _outboundSessions.get(key);
    496575                removed += sess.expireTags();
    497                 if (sess.availableTags() <= 0) {
     576                // don't kill a new session or one that's temporarily out of tags
     577                if (sess.getLastUsedDate() < now - (SESSION_LIFETIME_MAX_MS / 2) &&
     578                    sess.availableTags() <= 0) {
    498579                    iter.remove();
    499                     removed++;
     580                    removed++;   // just to have a non-zero return value?
    500581                }
    501582            }
     
    504585    }
    505586
    506     public String renderStatusHTML() {
     587    @Override
     588    public void renderStatusHTML(Writer out) throws IOException {
    507589        StringBuilder buf = new StringBuilder(1024);
    508         buf.append("<h2>Inbound sessions</h2>");
    509         buf.append("<table>");
     590        buf.append("<h2>Inbound sessions</h2>" +
     591                   "<table>");
    510592        Set<TagSet> inbound = getInboundTagSets();
    511593        Map<SessionKey, Set<TagSet>> inboundSets = new HashMap(inbound.size());
     594        // Build a map of the inbound tag sets, grouped by SessionKey
    512595        for (Iterator<TagSet> iter = inbound.iterator(); iter.hasNext();) {
    513596            TagSet ts = iter.next();
     
    516599            sets.add(ts);
    517600        }
     601        int total = 0;
     602        long now = _context.clock().now();
    518603        for (Iterator<SessionKey> iter = inboundSets.keySet().iterator(); iter.hasNext();) {
    519604            SessionKey skey = iter.next();
    520             Set<TagSet> sets = inboundSets.get(skey);
    521             buf.append("<tr><td><b>Session key</b>: ").append(skey.toBase64()).append("</td>");
    522             buf.append("<td><b># Sets:</b> ").append(sets.size()).append("</td></tr>");
    523             buf.append("<tr><td colspan=\"2\"><ul>");
     605            Set<TagSet> sets = new TreeSet(new TagSetComparator());
     606            sets.addAll(inboundSets.get(skey));
     607            buf.append("<tr><td><b>Session key</b>: ").append(skey.toBase64()).append("</td>" +
     608                       "<td><b># Sets:</b> ").append(sets.size()).append("</td></tr>" +
     609                       "<tr><td colspan=\"2\"><ul>");
    524610            for (Iterator<TagSet> siter = sets.iterator(); siter.hasNext();) {
    525611                TagSet ts = siter.next();
    526                 buf.append("<li><b>Received on:</b> ").append(new Date(ts.getDate())).append(" with ")
    527                    .append(ts.getTags().size()).append(" tags remaining</li>");
    528             }
    529             buf.append("</ul></td></tr>");
    530         }
    531         buf.append("</table>");
    532 
    533         buf.append("<h2><b>Outbound sessions</b></h2>");
    534 
    535         buf.append("<table>");
     612                int size = ts.getTags().size();
     613                total += size;
     614                buf.append("<li><b>Received:</b> ").append(DataHelper.formatDuration(now - ts.getDate())).append(" ago with ");
     615                buf.append(size).append(" tags remaining</li>");
     616            }
     617            buf.append("</ul></td></tr>\n");
     618            out.write(buf.toString());
     619            buf.setLength(0);
     620        }
     621        buf.append("<tr><th colspan=\"2\">Total tags: ").append(total).append(" (");
     622        buf.append(DataHelper.formatSize(32*total)).append("B)</th></tr>\n" +
     623                   "</table>" +
     624                   "<h2><b>Outbound sessions</b></h2>" +
     625                   "<table>");
     626        total = 0;
    536627        Set<OutboundSession> outbound = getOutboundSessions();
    537628        for (Iterator<OutboundSession> iter = outbound.iterator(); iter.hasNext();) {
    538629            OutboundSession sess = iter.next();
    539             buf.append("<tr><td><b>Target key:</b> ").append(sess.getTarget().toString()).append("<br>");
    540             buf.append("<b>Established:</b> ").append(new Date(sess.getEstablishedDate())).append("<br>");
    541             buf.append("<b>Last Used:</b> ").append(new Date(sess.getLastUsedDate())).append("<br>");
    542             buf.append("<b># Sets:</b> ").append(sess.getTagSets().size()).append("</td></tr>");
    543             buf.append("<tr><td><b>Session key:</b> ").append(sess.getCurrentKey().toBase64()).append("</td></tr>");
    544             buf.append("<tr><td><ul>");
    545             for (Iterator<TagSet> siter = sess.getTagSets().iterator(); siter.hasNext();) {
     630            Set<TagSet> sets = new TreeSet(new TagSetComparator());
     631            sets.addAll(sess.getTagSets());
     632            buf.append("<tr><td><b>Target key:</b> ").append(sess.getTarget().toBase64().substring(0, 64)).append("<br>" +
     633                       "<b>Established:</b> ").append(DataHelper.formatDuration(now - sess.getEstablishedDate())).append(" ago<br>" +
     634                       "<b>Last Used:</b> ").append(DataHelper.formatDuration(now - sess.getLastUsedDate())).append(" ago<br>" +
     635                       "<b>Session key:</b> ").append(sess.getCurrentKey().toBase64()).append("</td>" +
     636                       "<td><b># Sets:</b> ").append(sess.getTagSets().size()).append("</td></tr>" +
     637                       "<tr><td colspan=\"2\"><ul>");
     638            for (Iterator<TagSet> siter = sets.iterator(); siter.hasNext();) {
    546639                TagSet ts = siter.next();
    547                 buf.append("<li><b>Sent on:</b> ").append(new Date(ts.getDate())).append(" with ").append(
    548                                                                                                           ts.getTags()
    549                                                                                                             .size())
    550                    .append(" tags remaining</li>");
    551             }
    552             buf.append("</ul></td></tr>");
    553         }
    554         buf.append("</table>");
    555 
    556         return buf.toString();
    557     }
    558 
    559     class OutboundSession {
     640                int size = ts.getTags().size();
     641                total += size;
     642                buf.append("<li><b>Sent:</b> ").append(DataHelper.formatDuration(now - ts.getDate())).append(" ago with ");
     643                buf.append(size).append(" tags remaining; acked? ").append(ts.getAcked()).append("</li>");
     644            }
     645            buf.append("</ul></td></tr>\n");
     646            out.write(buf.toString());
     647            buf.setLength(0);
     648        }
     649        buf.append("<tr><th colspan=\"2\">Total tags: ").append(total).append(" (");
     650        buf.append(DataHelper.formatSize(32*total)).append("B)</th></tr>\n" +
     651                   "</table>");
     652
     653        out.write(buf.toString());
     654    }
     655
     656    /**
     657     *  Just for the HTML method above so we can see what's going on easier
     658     *  Earliest first
     659     */
     660    private static class TagSetComparator implements Comparator {
     661         public int compare(Object l, Object r) {
     662             return (int) (((TagSet)l).getDate() - ((TagSet)r).getDate());
     663        }
     664    }
     665
     666    private class OutboundSession {
    560667        private PublicKey _target;
    561668        private SessionKey _currentKey;
    562669        private long _established;
    563670        private long _lastUsed;
     671        /** before the first ack, all tagsets go here. These are never expired, we rely
     672            on the callers to call failTags() or ackTags() to remove them from this list. */
     673        private /* FIXME final FIXME */ List<TagSet> _unackedTagSets;
     674        /**
     675         *  As tagsets are acked, they go here.
     676         *  After the first ack, new tagsets go here (i.e. presumed acked)
     677         */
    564678        private /* FIXME final FIXME */ List<TagSet> _tagSets;
     679        /** set to true after first tagset is acked */
     680        private boolean _acked;
    565681
    566682        public OutboundSession(PublicKey target) {
     
    573689            _established = established;
    574690            _lastUsed = lastUsed;
    575             _tagSets = tagSets;
    576         }
    577 
    578         /** list of TagSet objects */
     691            _unackedTagSets = tagSets;
     692            _tagSets = new ArrayList();
     693        }
     694
     695        /**
     696         *  @return list of TagSet objects
     697         *  This is used only by renderStatusHTML().
     698         *  It includes both acked and unacked TagSets.
     699         */
    579700        List<TagSet> getTagSets() {
     701            List<TagSet> rv;
    580702            synchronized (_tagSets) {
    581                 return new ArrayList(_tagSets);
     703                rv = new ArrayList(_unackedTagSets);
     704                rv.addAll(_tagSets);
     705            }
     706            return rv;
     707        }
     708
     709        /**
     710         *  got an ack for these tags
     711         *  For tagsets delivered after the session was acked, this is a nop
     712         *  because the tagset was originally placed directly on the acked list.
     713         */
     714        void ackTags(TagSet set) {
     715            synchronized (_tagSets) {
     716                if (_unackedTagSets.remove(set)) {
     717                    _tagSets.add(set);
     718                    _acked = true;
     719                }
     720            }
     721            set.setAcked();
     722        }
     723
     724        /** didn't get an ack for these tags */
     725        void failTags(TagSet set) {
     726            synchronized (_tagSets) {
     727                _unackedTagSets.remove(set);
     728                _tagSets.remove(set);
    582729            }
    583730        }
     
    627774            synchronized (_tagSets) {
    628775                for (int i = 0; i < _tagSets.size(); i++) {
    629                     TagSet set = (TagSet) _tagSets.get(i);
     776                    TagSet set = _tagSets.get(i);
    630777                    if (set.getDate() + SESSION_TAG_DURATION_MS <= now) {
    631778                        _tagSets.remove(i);
     
    643790            synchronized (_tagSets) {
    644791                while (_tagSets.size() > 0) {
    645                     TagSet set = (TagSet) _tagSets.get(0);
     792                    TagSet set = _tagSets.get(0);
    646793                    if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
    647794                        SessionTag tag = set.consumeNext();
     
    657804        }
    658805
     806        /** @return the total number of tags in acked TagSets */
    659807        public int availableTags() {
    660808            int tags = 0;
     
    662810            synchronized (_tagSets) {
    663811                for (int i = 0; i < _tagSets.size(); i++) {
    664                     TagSet set = (TagSet) _tagSets.get(i);
    665                     if (set.getDate() + SESSION_TAG_DURATION_MS > now)
    666                         tags += set.getTags().size();
     812                    TagSet set = _tagSets.get(i);
     813                    if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
     814                        int sz = set.getTags().size();
     815                        // so tags are sent when the acked tags are below
     816                        // 30, 17, and 4.
     817                        if (!set.getAcked())
     818                            sz /= 3;
     819                        tags += sz;
     820                    }
    667821                }
    668822            }
     
    690844        }
    691845
     846        /**
     847         *  If the session has never been acked, put the TagSet on the unacked list.
     848         *  Otherwise, consider it good right away.
     849         */
    692850        public void addTags(TagSet set) {
    693851            _lastUsed = _context.clock().now();
    694             synchronized (_tagSets) {
    695                 _tagSets.add(set);
    696             }
    697         }
    698     }
    699 
    700     static class TagSet {
     852            if (_acked) {
     853                synchronized (_tagSets) {
     854                    _tagSets.add(set);
     855                }
     856            } else {
     857                synchronized (_unackedTagSets) {
     858                    _unackedTagSets.add(set);
     859                }
     860            }
     861        }
     862    }
     863
     864    private static class TagSet implements TagSetHandle {
    701865        private Set<SessionTag> _sessionTags;
    702866        private SessionKey _key;
    703867        private long _date;
    704         private Exception _createdBy;
     868        //private Exception _createdBy;
     869        /** did we get an ack for this tagset? */
     870        private boolean _acked;
    705871
    706872        public TagSet(Set<SessionTag> tags, SessionKey key, long date) {
     
    710876            _key = key;
    711877            _date = date;
    712             if (true) {
    713                 long now = I2PAppContext.getGlobalContext().clock().now();
    714                 _createdBy = new Exception("Created by: key=" + _key.toBase64() + " on "
    715                                            + new Date(now) + "/" + now
    716                                            + " via " + Thread.currentThread().getName());
    717             }
     878            //if (true) {
     879            //    long now = I2PAppContext.getGlobalContext().clock().now();
     880            //    _createdBy = new Exception("Created by: key=" + _key.toBase64() + " on "
     881            //                               + new Date(now) + "/" + now
     882            //                               + " via " + Thread.currentThread().getName());
     883            //}
    718884        }
    719885
     
    741907
    742908        public void consume(SessionTag tag) {
    743             if (contains(tag)) {
    744                 _sessionTags.remove(tag);
    745             }
    746         }
    747 
     909            _sessionTags.remove(tag);
     910        }
     911
     912        /** let's do this without counting the elements first */
    748913        public SessionTag consumeNext() {
    749             if (_sessionTags.size() <= 0) {
     914            SessionTag first;
     915            try {
     916                first = _sessionTags.iterator().next();
     917            } catch (NoSuchElementException nsee) {
    750918                return null;
    751919            }
    752 
    753             SessionTag first = (SessionTag) _sessionTags.iterator().next();
    754920            _sessionTags.remove(first);
    755921            return first;
    756922        }
    757923       
    758         public Exception getCreatedBy() { return _createdBy; }
     924        //public Exception getCreatedBy() { return _createdBy; }
     925
     926        public void setAcked() { _acked = true; }
     927        public boolean getAcked() { return _acked; }
    759928       
     929/******    this will return a dup if two in the same ms, so just use java
    760930        @Override
    761931        public int hashCode() {
    762932            long rv = 0;
    763             if (_key != null) rv = rv * 7 + _key.hashCode();
     933            if (_key != null) rv = _key.hashCode();
    764934            rv = rv * 7 + _date;
    765935            // no need to hashCode the tags, key + date should be enough
     
    771941            if ((o == null) || !(o instanceof TagSet)) return false;
    772942            TagSet ts = (TagSet) o;
    773             return DataHelper.eq(ts.getAssociatedKey(), getAssociatedKey())
     943            return DataHelper.eq(ts.getAssociatedKey(), _key)
    774944                   //&& DataHelper.eq(ts.getTags(), getTags())
    775                    && ts.getDate() == getDate();
     945                   && ts.getDate() == _date;
     946        }
     947******/
     948
     949        @Override
     950        public String toString() {
     951            StringBuilder buf = new StringBuilder(256);
     952            buf.append("TagSet established: ").append(new Date(_date));
     953            buf.append(" Session key: ").append(_key.toBase64());
     954            buf.append(" Size: ").append(_sessionTags.size());
     955            buf.append(" Acked? ").append(_acked);
     956            return buf.toString();
    776957        }
    777958    }
  • core/java/src/net/i2p/data/SessionKey.java

    r3a1c042c r2dd650d  
    9090    @Override
    9191    public String toString() {
     92        return "SessionKey " + toBase64();
     93      /****
    9294        if (true) return super.toString();
    9395        StringBuilder buf = new StringBuilder(64);
     
    104106        buf.append("]");
    105107        return buf.toString();
     108      ****/
    106109    }
    107110}
  • core/java/src/net/i2p/data/SessionTag.java

    r3a1c042c r2dd650d  
    5959    }
    6060
     61    @Override
     62    public String toString() {
     63        return "SessionTag " + toBase64();
     64    }
    6165}
  • history.txt

    r3a1c042c r2dd650d  
     12009-09-21 sponge
     2    * fixups to SlackBuilds. requiredbuilder does the wrong thing, and
     3      thinks that java is perl! This isn't really a big deal,
     4      the file format is simple enough and the requirements are known.
     5
     62009-09-07 mkvore
     7    * removes a SAM v1&2 bug
     8
     92009-09-04 zzz
     10    * SessionKeyManager, OCMOSJ, Garlic:
     11      - Enable per-client SessionKeyManagers for better anonymity
     12      - tagsDelivered() now means tags are sent, not acked.
     13      - OCMOSJ uses the new TagSetHandle object returned from tagsDelivered()
     14        to call tagsAcked() or failTags() as appropriate.
     15      - Assume tags delivered on an established session to
     16        reduce streaming lib stalls caused by massive tag deliveries;
     17        should increase throughput and window sizes on long-lived streams
     18      - Unacked tagsets on a new session are stored on a separate list
     19      - Don't kill an OB Session just because it's temporarily out of tags
     20      - Increase min tag threshold to 30 (was 20) due to new speculative
     21        tags delivered scheme, and to increase effective max window
     22      - More Java 5 and dead code cleanups, and more comments and javadoc,
     23        debug logging cleanups
     24      - Key toString()s for easier debugging
     25      - HandleGarlicMessageJob: cleanup of unused things
     26    * Tunnel TestJob:
     27      - Consume the tag after a failed test so it doesn't
     28        stay in the SKM
     29      - Disable tests with router.disableTunnelTesting=true
     30    * configkeyring.jsp: Add delete and cancel buttons
     31    * Logging: Fix directory for rotated log
     32    * TunnelDispatcher: Cleanup
     33
     342009-09-02 sponge
     35    * Small logic fix for dr|z3d
     36
     372009-08-28 zzz
     38    * Client: Fail if no date handshake after 30s or no leaseset
     39      after 5m, rather than hanging forever.
     40    * Console:
     41      - Prevent OOMs in NewsFetcher or StatsSummarizer from
     42        killing the router
     43      - Fix favicon (-17)
     44    * Data: Speed up many hashcodes
     45    * DataHelper: Fix byte array hashcode for small arrays
     46    * DecayingBloomFilter:
     47      - Replace with new DecayingHashSet for 3 of 4 uses,
     48        and also in the 4th if the router is low-bandwidth.
     49        Saves 8 MB heap.
     50    * EepGet, I2PSnark:
     51      - New I2PSocketEepGet fetches through existing tunnels
     52        rather than through the proxy
     53      - Use new eepget for i2psnark
     54      - Add a fake user agent for non-proxied fetches
     55      - Cleanups
     56    * NetDb:
     57      - oops, store leaseset locally even when shutting down
     58        (fix -16)
     59      - Java 5 cleanups
     60    * PRNG:
     61      - Rename config option to prng.buffers (was router.prng.buffers)
     62      - Change the default from 16 to 2 for I2PAppContext (saves 3.5MB)
     63    * Tunnel:
     64      - Adjust the random drop probability for the message size
     65      - Concurrentify HashSetIVValidator
     66    * TunnelPool:
     67      - Don't test tunnels when shutting down
     68      - Less rates
     69      - Java 5 cleanups
     70
     712009-08-24 zzz
     72    * ClientManager:
     73      - Prevent client destination theft by rejecting duplicates
     74      - Java 5 cleanups
     75    * Console:
     76      - Put favicon on every page
     77      - Make every page UTF-8, ☃ safe for snowmen
     78      - Remove options boxes on configtunnels.jsp
     79      - Fix UTF-8 form submission (i2ptunnel too)
     80      - Throw 403 instead of 404 from flags.jsp and viewstat.jsp
     81        so we don't render error.jsp
     82    * I2CP: Fix the SessionConfig serializer in DataHelper,
     83      so that UTF-8 tunnel names are not corrupted by
     84      I2CP and can be displayed on the console
     85    * Message: Move 2 unused classes out of the router lib (~15KB)
     86      (more SKM prep)
     87    * Message, I2PSession, SessionKeyManager, Console:
     88      Prep for SessionKeyManager work in the router -
     89      Fix up SKM renderStatusHTML(); add debug.jsp to see it;
     90      Redefine getClientSessionKeyManager();
     91      More cleanups
     92    * Ministreaming: Kill deprecation warnings
     93    * profiles.jsp: Bulletproofing, less memory usage
     94    * Streaming, I2PSession:
     95      Prep for SessionKeyManager work in the router -
     96      Comment out, deprecate, and javadoc for unused keys and tags,
     97      they are vestiges of end-to-end crypto
     98    * Updates: Verify zip at startup before extracting
     99    * Wrapper: Take a couple fields out of the log so it's narrower
     100
    11012009-08-20 zzz
    2102    * Config files:
  • installer/resources/themes/console/classic/console.css

    r3a1c042c r2dd650d  
    104104}
    105105
     106/* console error messages */
     107
     108div.sorry {
     109     padding: 20px;
     110     background: #ddf;
     111     margin: -2px 1px 0 195px;
     112     border: 5px solid #bbf;
     113     text-align: justify;
     114     -moz-box-shadow: inset 0px 0px 0px 1px #d00;
     115     word-wrap: break-word;
     116     font-weight: bold;
     117     color: #001;
     118}
     119
     120div.sorry hr {
     121     color: #001;
     122     background: #001;
     123     height: 1px;
     124     border: 1px solid #001;
     125     margin: 10px 0;
     126}
     127
    106128div.toolbar {
    107129     margin: 0em 0em 2em 0em;
     
    124146     color: inherit;
    125147     margin: 0;
    126      padding: 7px 1px;
     148     padding: 10px 1px 7px 1px;
    127149     text-align: center !important;
    128150     border: 5px solid #bbf;
  • installer/resources/themes/console/dark/console.css

    r3a1c042c r2dd650d  
    223223     word-wrap: break-word;
    224224}
     225
     226/* console error messages */
     227
     228div.sorry {
     229     margin: 5px 15px 10px 220px;
     230     padding: 20px 20px 20px 75px;
     231     background: #005;
     232     border: 1px solid #99f;
     233     -moz-border-radius: 4px;
     234     -khtml-border-radius: 4px;
     235     border-radius: 4px;
     236     text-align: justify;
     237     background-image:url("images/errortriangle.png");
     238     background-position:15px center;
     239     background-repeat:no-repeat;
     240     -moz-box-shadow: inset 0px 0px 0px 1px #d00;
     241     word-wrap: break-word;
     242     font-weight: bold;
     243     color: #eef;
     244}
     245
     246div.sorry hr {
     247     color: #eef;
     248     background: #eef;
     249     height: 1px;
     250     border: 1px solid #eef;
     251     margin: 10px 0;
     252}     
    225253
    226254div.main {
  • installer/resources/themes/console/light/console.css

    r3a1c042c r2dd650d  
    22
    33body {
    4      margin: 25px 10px 0 5px;
     4     margin: 15px 0 0 10px;
    55     padding: 0em;
    66     text-align: center;
     
    2424     font: 8pt "Lucida Console", "DejaVu Sans Mono", Courier, mono;
    2525     color: #333;
     26     margin: 10px;
    2627}
    2728
     
    7980     float: left;
    8081     width: 215px;
    81      margin: 0 0 10px 20px;
     82     margin: 0 0 10px 0px;
    8283     padding: 0;
    8384     border: 0;
     
    184185}
    185186
    186 
    187187div.routersummary tr:nth-child(even) {
    188188     background-color: #f60;
     
    194194     background-image: none !important;
    195195}
     196
     197/* proxy error messages */
    196198
    197199div.warning {
     
    213215}
    214216
     217/* console error messages */
     218
     219div.sorry {
     220     margin: 5px 15px 10px 220px;
     221     padding: 20px 20px 20px 75px;
     222     background: #ffb;
     223     border: 1px solid #002;
     224     -moz-border-radius: 4px;
     225     -khtml-border-radius: 4px;
     226     border-radius: 4px;
     227     text-align: justify;
     228     background-image: url("images/errortriangle.png");
     229     background-position: 15px center;
     230     background-repeat: no-repeat;
     231     -moz-box-shadow: inset 0px 0px 0px 1px #d00;
     232     word-wrap: break-word;
     233     font-weight: bold;
     234     color: #331;
     235}
     236
     237div.sorry hr {
     238     color: #552;
     239     background: #552;
     240     height: 1px;
     241     border: 1px solid #552;
     242     margin: 10px 0;
     243}     
     244
    215245div.main {
    216      margin: 0px 0px 20px 220px;
     246     margin: 0px 0px 20px 195px;
    217247     padding: 0 15px 15px 25px;
    218248     background: #eef;
     
    238268
    239269div.news {
    240      margin: 0px 15px 20px 245px;
     270     margin: 0px 15px 10px 220px;
    241271     padding: 20px 30px 20px 30px;
    242272     border: 1px solid #003;
     
    303333div.confignav {
    304334     padding: 15px 10px !important;
    305      margin: 0 0 25px 0;
     335     margin: 0 0px 15px 0;
    306336     background: #ddf url('images/lightbluetile.png');
    307337     -moz-border-radius: 4px;
     
    317347
    318348div.configure {
    319      padding: 0 15px 15px 15px !important;
    320      margin: 10px 0px 25px 0;
     349     padding: 0 15px 0px 15px !important;
     350     margin: 0px 0px 15px 0;
    321351     background: #ddf url('images/lightbluetile.png');
    322352     -moz-border-radius: 4px;
     
    326356     -moz-box-shadow: inset 0px 0px 1px 0px #002;
    327357     min-width: 400px;
     358}
     359
     360div.configure h3, div.graphspanel h3 {
     361     border: 1px solid #002;
     362     border-left: 5px solid #002;
     363     padding: 3px 5px 3px 5px;
     364     margin: 15px 0 15px 0;
     365     border-radius: 0 4px 4px 0;
     366     -moz-border-radius: 0 4px 4px 0;
     367     -khtml-border-radius: 0 4px 4px 0;
     368     background: #eef;
    328369}
    329370
     
    366407div.messages {
    367408     padding: 10px;
    368      margin: 10px 0 20px 0;
     409     margin: 10px 0 15px 0;
    369410     background: #ddf;
    370411     -moz-border-radius: 4px;
     
    398439     width: 100%;
    399440     border: 1px solid #000022;
    400      margin: 5px 0px 5px 0px;
     441     margin: 10px -15px 5px 0px;
    401442     cell-padding: 1px;
    402443     font-size: 7pt;
     
    463504     list-style: square;
    464505     margin: 2px 5px 0px 20px;
    465      padding: 1px 20px 1px 10px;
     506     padding: 1px 10px 1px 10px;
    466507     line-height: 150%;
    467508     word-wrap: break-word;
     
    529570     color: #002;
    530571     padding: 10px 15px;
    531      margin: 0 15px 25px 245px;
     572     margin: 0 15px 15px 220px;
    532573     font: normal bold 16pt/120% "Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif;
    533574     letter-spacing: 0.15em;
     
    555596     -moz-border-radius: 4px;
    556597     -khtml-border-radius: 4px;
    557      margin: 25px 0 20px 0 !important;
     598     margin: 15px 0px 10px 0 !important;
    558599     -moz-box-shadow: inset 0px 0px 1px 0px #002;
    559600     word-wrap: break-word;
     
    572613     border-left: 5px solid #002;
    573614     padding: 3px 5px 3px 5px;
    574      margin: 20px 0 15px 0;
     615     margin: 10px 0 15px 0;
    575616     border-radius: 0 4px 4px 0;
    576617     -moz-border-radius: 0 4px 4px 0;
     
    765806
    766807.joblog {
    767      margin: 25px 0 25px 0;
    768      padding: 20px 40px 20px 40px !important;
     808     margin: 15px 0;
     809     padding: 10px 20px !important;
    769810     border: 1px solid #003;
    770811     background-color: #004;
     
    785826 .joblog:ul {
    786827     word-wrap: break-word !important;
     828}
     829
     830.joblog table {
     831     margin-top: 10px;
    787832}
    788833
  • installer/resources/themes/console/snark.css

    r3a1c042c r2dd650d  
    22
    33body {
    4         background-color: #eef;
    5         color:#001;
    6         font-family:"Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif;
    7   font-size: 8pt;
     4     background: #eef;
     5     color: #001;
     6     font: 8pt "Lucida Sans Unicode","Bitstream Vera Sans",Verdana,Tahoma,Helvetica,sans-serif;
    87}
    98
    109.snarkTitle {
    11         font-size: 12pt;
    12         font-weight: bold;
    13         text-align: center;
    14 }
    15 
    16 .snarkRefresh:link, .snarkRefresh:visited {
    17   text-decoration: none !important;
    18   text-transform: uppercase !important;
    19   padding: 0 16px;
    20   letter-spacing: 0.05em;
    21   font-weight: bold;
    22   font-size: 11pt;
    23   color: #005;
    24   text-shadow: 0px 0px 1px rgba(0, 0, 148, 0.9);
    25   }
    26  
    27  .snarkRefresh:hover{
    28   text-decoration: none !important;
    29   text-transform: uppercase !important;
    30   padding: 0 16px;
    31   letter-spacing: 0.05em;
    32   font-weight: bold;
    33   font-size: 11pt;
    34   color: #f60;
    35   border-bottom: 3px solid #f60;
    36   border-top: 3px solid #f60;
    37   text-shadow: 0px 0px 1px rgba(255, 128, 0, 0.9);
    38   }
    39  
    40 .snarkRefresh:active{
    41   text-decoration: none !important;
    42   text-transform: uppercase !important;
    43   padding: 0 16px;
    44   letter-spacing: 0.05em;
    45   font-weight: bold;
    46   font-size: 11pt;
    47   color: #f30;
    48   border-bottom: 3px solid #f30;
    49   border-top: 3px solid #f30;
    50   text-shadow: 0px 0px 1px rgba(255, 32, 0, 0.5);
    51   }
     10     font-size: 12pt;
     11     font-weight: bold;
     12     text-align: center;
     13}
     14
     15.snarkRefresh:link,.snarkRefresh:visited {
     16     text-decoration: none !important;
     17     text-transform: uppercase !important;
     18     padding: 0 16px;
     19     letter-spacing: 0.05em;
     20     font-weight: bold;
     21     font-size: 11pt;
     22     color: #005;
     23     text-shadow: 0px 0px 1px rgba(0,0,148,0.9);
     24}
     25
     26.snarkRefresh:hover {
     27     text-decoration: none !important;
     28     text-transform: uppercase !important;
     29     padding: 0 16px;
     30     letter-spacing: 0.05em;
     31     font-weight: bold;
     32     font-size: 11pt;
     33     color: #f60;
     34     border-bottom: 3px solid #f60;
     35     border-top: 3px solid #f60;
     36     text-shadow: 0px 0px 1px rgba(255,128,0,0.9);
     37}
     38
     39.snarkRefresh:active {
     40     text-decoration: none !important;
     41     text-transform: uppercase !important;
     42     padding: 0 16px;
     43     letter-spacing: 0.05em;
     44     font-weight: bold;
     45     font-size: 11pt;
     46     color: #f30;
     47     border-bottom: 3px solid #f30;
     48     border-top: 3px solid #f30;
     49     text-shadow: 0px 0px 1px rgba(255,32,0,0.5);
     50}
    5251
    5352.snarkMessages {
    54   background-color: #f83;
    55   font-family: "Lucida Console", "DejaVu Sans Mono", Courier, mono !important;
    56   font-size: 9pt;
    57   font-weight: bold;
    58   text-align: left;
    59   margin: 0 0px 10px 0px;
    60   padding: 0;
    61   border-spacing: 0px;
    62   -moz-border-radius: 4px 0 0 0;
    63   -khtml-border-radius: 4px;
    64   border-radius: 4px;
    65   border: 2px solid #930;
    66   text-align: left;
    67   overflow: auto;           
    68   background: #f40 url('../console/images/orangetile.png');
    69   color: #531;
    70   height: 64px;
    71   width: auto;
     53     font: bold 9pt "Lucida Console","DejaVu Sans Mono",Courier,mono !important;
     54     text-align: left;
     55     margin: 0 0px 10px 0px;
     56     padding: 0;
     57     border-spacing: 0px;
     58     -moz-border-radius: 4px 0 0 0;
     59     -khtml-border-radius: 4px;
     60     border-radius: 4px;
     61     border: 2px solid #930;
     62     overflow: auto;
     63     color: #531;
     64     height: 64px;
     65     width: auto;
     66     background: #f83 url('../console/images/orangetile.png');
    7267}
    7368
    7469pre {
    75   font-family: "Lucida Console", "DejaVu Sans Mono", Courier, mono !important;
    76   width: 100%;
    77   font-size: 8pt;
    78   padding: 0;
    79   text-align: left !important;
    80   height: 8px;
     70     width: 100%;
     71     font: 8pt "Lucida Console","DejaVu Sans Mono",Courier,mono !important;
     72     padding: 0;
     73     text-align: left !important;
     74     height: 8px;
    8175}
    8276
    8377table {
    84         margin: 0px 0px 10px 0px;
    85         border: 0px;
    86         padding: 0px;
    87         border-width: 0px;
    88         border-spacing: 0px;
    89   border-collapse: collapse;
     78     margin: 0px 0px 10px 0px;
     79     border: 0px;
     80     padding: 0px;
     81     border-spacing: 0px;
     82     border-collapse: collapse;
    9083}
    9184
    9285th {
    93         padding: 5px;
    94   font-size: 8pt;
    95   border-top: 1px outset #001;
    96   border-bottom: 1px inset #001; 
    97   background: #f60 url('/themes/console/images/tabletitleorange.png') repeat-x;
    98 /*  text-align: right; */
    99   whitespace: nowrap;
     86     padding: 4px;
     87     font-size: 8pt;
     88     border-top: 1px outset #001;
     89     border-bottom: 1px inset #001;
     90     background: #f60 url('/themes/console/images/tabletitleorange.png') repeat-x;
     91     whitespace: nowrap;
    10092}
    10193
    10294.SnarkTorrents {
    103         margin: 0;
    104         border: 1px solid #001;
    105   background-color: #f9f;
     95     margin: 0;
     96     border: 1px solid #001;
     97     background: #f9f;
    10698}
    10799
    108100td {
    109         padding: 5px;
    110 /*  text-align: right;*/
    111 }
     101     padding: 4px;
     102}
     103
    112104.snarkTorrentEven {
    113         background-color: #fb1;
    114   font-size: 7pt;
    115 }
     105     background: #fb1;
     106     font-size: 7pt;
     107}
     108
    116109.snarkTorrentOdd {
    117         background-color: #fa1;
    118   font-size: 7pt;
    119 }
     110     background: #fa1;
     111     font-size: 7pt;
     112}
     113
    120114.snarkNewTorrent {
    121         font-size: 9pt;
    122 }
     115     font-size: 9pt;
     116}
     117
    123118.snarkAddInfo {
    124         font-size: 9pt;
    125   line-height: 130% !important;
    126 }
     119     font-size: 9pt;
     120     line-height: 130% !important;
     121}
     122
    127123.snarkConfigTitle {
    128         font-size: 11pt;
    129   font-weight: bold;
    130   text-decoration: underline;
     124     font-size: 11pt;
     125     font-weight: bold;
     126     text-decoration: underline;
     127     text-transform: uppercase;
     128     text-shadow: 0px 0px 2px rgba(172,172,192,0.9);
    131129}
    132130
    133131.snarkConfig {
    134   font-size: 10pt;
     132     font-size: 10pt;
     133     width: 100%;
    135134}
    136135
    137136.page {
    138         background-color: #fff;
    139         color:#310;
    140   min-width: 800px !important;
    141 /*  max-width: 800px !important; */
    142   margin: 5px 0px;
    143   padding: 10px 10px 0px 10px;
    144   -moz-border-radius: 4px;
    145   -khtml-border-radius: 4px;
    146   border-radius: 4px;
    147   border: 1px solid #001;
    148   font-size: 9pt !important;
    149   line-height: 160% !important;
    150   -moz-box-shadow: inset 0px 0px 1px 0px #002;
    151   text-align: center;
    152   background: #ddf url('../console/light/images/lightbluetile.png');
    153   opacity: 1.0;
     137     background: #fff;
     138     color: #310;
     139     min-width: 800px !important;
     140     margin: 5px 0 0 0;
     141     padding: 10px 10px 0px 10px;
     142     -moz-border-radius: 4px;
     143     -khtml-border-radius: 4px;
     144     border-radius: 4px;
     145     border: 1px solid #001;
     146     font-size: 9pt !important;
     147     line-height: 160% !important;
     148     -moz-box-shadow: inset 0px 0px 1px 0px #002;
     149     text-align: center;
     150     opacity: 1.0;
    154151}
    155152
    156153form {
    157   line-height: 250%
    158 }
    159 
    160 p {
    161   line-height: 150%
     154     line-height: 250%;
     155}
     156
     157p {
     158     line-height: 150%;
     159}
     160
     161hr {
     162     color: #003;
     163     background: #003;
     164     height: 1px;
     165     border: 0px solid #003;
     166     width: 100%;
     167     margin: 10px 0 7px 0;
     168     text-align: center;
    162169}
    163170
    164171a:link {
    165   padding 5px;
    166 }
    167 
    168 hr {
    169   color: #003;
    170   background: #003;
    171   height: 1px;
    172   border: 0px solid #003;
    173   width: 100%;
    174   margin: 10px 0 7px 0;
    175   text-align: center;
    176 }
    177 
    178 a:link{
    179   color: #930;
    180   text-decoration: none;
    181   font-weight: bold;
    182   word-wrap: break-word;
    183 }
    184 
    185 a:visited{
    186   color: #606;
    187   text-decoration: none;
    188   font-weight: bold;
    189 }
    190 
    191 a:hover{
    192   color: #900;
    193   font-weight: bold;
     172     color: #930;
     173     text-decoration: none;
     174     font-weight: bold;
     175     word-wrap: break-word;
     176}
     177
     178a:visited {
     179     color: #606;
     180     text-decoration: none;
     181     font-weight: bold;
     182}
     183
     184a:hover {
     185     color: #900;
     186     font-weight: bold;
    194187}
    195188
    196189input {
    197 /*  font-family: "Lucida Console", "DejaVu Sans Mono", Courier, mono !important;*/
    198   font-size: 9pt;
    199   font-weight: bold;
    200   text-align: left;
    201   padding: 2px;
    202 }     
     190     font-size: 9pt;
     191     font-weight: bold;
     192     text-align: left;
     193     padding: 2px;
     194}
    203195
    204196select {
    205         font-family:"Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif;
    206   background-color: #ffe;
    207   color: #310;
    208   font-size: 9pt;
     197     background: #ffe;
     198     color: #310;
     199     font: 9pt "Lucida Sans Unicode","Bitstream Vera Sans",Verdana,Tahoma,Helvetica,sans-serif;
    209200}
    210201
    211202img {
    212   border: none;
    213   margin: 5px 5px 0px 5px;
    214   opacity: 1.0;
    215   line-height: 100%
    216 }
    217 
    218 img:hover{
    219   border: none;
    220   margin: 5px 5px 0px 5px;
    221   opacity: 0.5;
    222   line-height: 100%
    223 }
    224 
    225 
    226 div.section {
    227   margin: 0 0 10px 0;
    228   padding: 10px;
    229   background: #ffe;
    230   border: 1px solid #001;
    231   text-align: center;
    232   color: #001;
    233   -moz-border-radius: 4px;
    234   -khtml-border-radius: 4px;
    235   border-radius: 4px;
    236   -moz-box-shadow: inset 0px 0px 1px 0px #002;
    237   word-wrap: break-word;
    238   text-align: center;
    239   background: #ffe url('../console/light/images/tabletile.png');
    240   opacity: 1.0;
    241 }
    242 
    243 div.mainsection {
    244   margin: 0 0 10px 0;
    245   padding: 10px;
    246   background: #ffe;
    247   border: 1px solid #001;
    248   text-align: center;
    249   color: #001;
    250   -moz-border-radius: 4px;
    251   -khtml-border-radius: 4px;
    252   border-radius: 4px;
    253   -moz-box-shadow: inset 0px 0px 1px 0px #002;
    254   word-wrap: break-word;
    255   text-align: center;
    256   background: #ffe url('../console/light/images/tabletile.png');
    257   opacity: 1.0;
     203     border: none;
     204     margin: 5px 5px 0px 5px;
     205     opacity: 1.0;
     206     line-height: 100%;
     207}
     208
     209img: hover {
     210     border: none;
     211     margin: 5px 5px 0px 5px;
     212     opacity: 0.5;
     213     line-height: 100%;
     214}
     215
     216div.section,div.mainsection {
     217     margin: 0 0 10px 0;
     218     padding: 10px;
     219     border: 1px solid #001;
     220     color: #001;
     221     -moz-border-radius: 4px;
     222     -khtml-border-radius: 4px;
     223     border-radius: 4px;
     224     -moz-box-shadow: inset 0px 0px 1px 0px #002;
     225     word-wrap: break-word;
     226     text-align: center;
     227     background: #ffe url('../console/light/images/tabletile.png');
     228     opacity: 1.0;
    258229}
    259230
    260231div.newtorrentsection {
    261   margin: 0 0 10px 0;
    262   padding: 10px;
    263   background: #ffe;
    264   border: 1px solid #001;
    265   text-align: center;
    266   color: #001;
    267   -moz-border-radius: 4px;
    268   -khtml-border-radius: 4px;
    269   border-radius: 4px;
    270   -moz-box-shadow: inset 0px 0px 1px 0px #002;
    271   word-wrap: break-word;
    272   text-align: center;
    273   background: #ffe url('../console/images/yellowtile.png');
    274   opacity: 1.0;
     232     margin: 0 0 10px 0;
     233     padding: 0 10px 10px 10px;
     234     border: 1px solid #001;
     235     text-align: center;
     236     color: #001;
     237     -moz-border-radius: 4px;
     238     -khtml-border-radius: 4px;
     239     border-radius: 4px;
     240     -moz-box-shadow: inset 0px 0px 1px 0px #002;
     241     word-wrap: break-word;
     242     background: #bb4 url('../console/images/yellowtile.png');
     243     opacity: 1.0;
    275244}
    276245
    277246div.addtorrentsection {
    278   margin: 0 0 10px 0;
    279   padding: 10px;
    280   background: #ffe;
    281   border: 1px solid #001;
    282   text-align: center;
    283   color: #001;
    284   -moz-border-radius: 4px;
    285   -khtml-border-radius: 4px;
    286   border-radius: 4px;
    287   -moz-box-shadow: inset 0px 0px 1px 0px #002;
    288   word-wrap: break-word;
    289   text-align: center;
    290   background: #ffe url('../console/images/greentile.png');
    291   opacity: 1.0;
     247     margin: 0 0 10px 0;
     248     padding: 0 10px 10px 10px;
     249     border: 1px solid #001;
     250     text-align: center;
     251     color: #001;
     252     -moz-border-radius: 4px;
     253     -khtml-border-radius: 4px;
     254     border-radius: 4px;
     255     -moz-box-shadow: inset 0px 0px 1px 0px #002;
     256     word-wrap: break-word;
     257     background: #7f7 url('../console/images/greentile.png');
     258     opacity: 1.0;
    292259}
    293260
    294261div.configsection {
    295   margin: 0;
    296   padding: 10px;
    297   background: #ffe;
    298   border: 1px solid #001;
    299   color: #ffb;
    300   -moz-border-radius: 4px;
    301   -khtml-border-radius: 4px;
    302   border-radius: 4px;
    303   -moz-box-shadow: inset 0px 0px 0px 1px #900;
    304   word-wrap: break-word;
    305   text-align: center;
    306   background: #ffe url('../console/light/images/darkbluetile.png');
    307   font-weight: bold; /* red tile needs bold text! */
    308 }
    309 
    310 div.configsection a{
    311   color: #f90;
    312 }
    313 
    314 div.configsection a:hover{
    315   color: #f60;
    316   text-decoration: underline;
     262     margin: 0;
     263     padding: 0 10px 10px 10px;
     264     border: 1px solid #001;
     265     color: #ffb;
     266     -moz-border-radius: 4px;
     267     -khtml-border-radius: 4px;
     268     border-radius: 4px;
     269     -moz-box-shadow: inset 0px 0px 0px 1px #900;
     270     word-wrap: break-word;
     271     text-align: center;
     272     background: #700 url('../console/light/images/darkbluetile.png');
     273     font-weight: bold;/* red tile needs bold text! */
     274}
     275
     276div.configsection a {
     277     color: #f90;
     278}
     279
     280div.configsection a: hover {
     281     color: #f60;
     282     text-decoration: underline;
    317283}
    318284
    319285.snarknavbar {
    320   margin: 0 0 10px 0 !important;
    321   padding: 10px;
    322   border: 1px solid #001;
    323   -moz-border-radius: 4px;
    324   -khtml-border-radius: 4px;
    325   border-radius: 4px;
    326   background: #eef;
    327   -moz-box-shadow: inset 0px 0px 1px 0px #002;
    328   background: #ddf url('../console/light/images/tabletile.png');
    329   text-transform: uppercase !important;
    330   letter-spacing: 0.05em;
    331   font-weight: bold;
    332   font-size: 11pt;
    333   color: #001;
    334   text-shadow: 0px 0px 1px rgba(0, 0, 148, 0.9);
    335 }
     286     margin: 0 0 10px 0 !important;
     287     padding: 10px;
     288     border: 1px solid #001;
     289     -moz-border-radius: 4px;
     290     -khtml-border-radius: 4px;
     291     border-radius: 4px;
     292     -moz-box-shadow: inset 0px 0px 1px 0px #002;
     293     background: #ddf url('../console/light/images/tabletile.png');
     294     text-transform: uppercase !important;
     295     letter-spacing: 0.05em;
     296     font-weight: bold;
     297     font-size: 11pt;
     298     color: #001;
     299     text-shadow: 0px 0px 1px rgba(0,0,148,0.9);
     300 }
  • router/java/src/net/i2p/router/ClientManagerFacade.java

    r3a1c042c r2dd650d  
    8686     * @return set of Destination objects
    8787     */
    88     public Set listClients() { return Collections.EMPTY_SET; }
     88    public Set<Destination> listClients() { return Collections.EMPTY_SET; }
    8989   
    9090    /**
     
    9393     */
    9494    public abstract SessionConfig getClientSessionConfig(Destination dest);
    95     public abstract SessionKeyManager getClientSessionKeyManager(Destination dest);
     95    public abstract SessionKeyManager getClientSessionKeyManager(Hash dest);
    9696    public void renderStatusHTML(Writer out) throws IOException { }
    9797}
  • router/java/src/net/i2p/router/DummyClientManagerFacade.java

    r3a1c042c r2dd650d  
    4242   
    4343    public SessionConfig getClientSessionConfig(Destination _dest) { return null; }
    44     public SessionKeyManager getClientSessionKeyManager(Destination _dest) { return null; }
     44    public SessionKeyManager getClientSessionKeyManager(Hash _dest) { return null; }
    4545   
    4646    public void requestLeaseSet(Hash dest, LeaseSet set) {}
  • router/java/src/net/i2p/router/RouterVersion.java

    r3a1c042c r2dd650d  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 16;
     21    public final static long BUILD = 20;
    2222    /** for example "-test" */
    2323    public final static String EXTRA = "";
  • router/java/src/net/i2p/router/client/ClientConnectionRunner.java

    r3a1c042c r2dd650d  
    1919
    2020import net.i2p.crypto.SessionKeyManager;
     21import net.i2p.crypto.TransientSessionKeyManager;
    2122import net.i2p.data.Destination;
    2223import net.i2p.data.Hash;
     
    189190            _log.debug("SessionEstablished called for destination " + _destHashCache.toBase64());
    190191        _config = config;
    191         // per-dest unimplemented
    192         //if (_sessionKeyManager == null)
    193         //    _sessionKeyManager = new TransientSessionKeyManager(_context);
    194         //else
    195         //    _log.error("SessionEstablished called for twice for destination " + _destHashCache.toBase64().substring(0,4));
     192        // per-destination session key manager to prevent rather easy correlation
     193        if (_sessionKeyManager == null)
     194            _sessionKeyManager = new TransientSessionKeyManager(_context);
     195        else
     196            _log.error("SessionEstablished called for twice for destination " + _destHashCache.toBase64().substring(0,4));
    196197        _manager.destinationEstablished(this);
    197198    }
  • router/java/src/net/i2p/router/client/ClientManager.java

    r3a1c042c r2dd650d  
    4343    private Log _log;
    4444    private ClientListenerRunner _listener;
    45     private final HashMap _runners;        // Destination --> ClientConnectionRunner
    46     private final Set _pendingRunners; // ClientConnectionRunner for clients w/out a Dest yet
     45    private final HashMap<Destination, ClientConnectionRunner> _runners;        // Destination --> ClientConnectionRunner
     46    private final Set<ClientConnectionRunner> _pendingRunners; // ClientConnectionRunner for clients w/out a Dest yet
    4747    private RouterContext _ctx;
    4848
     
    9191        _log.info("Shutting down the ClientManager");
    9292        _listener.stopListening();
    93         Set runners = new HashSet();
    94         synchronized (_runners) {
    95             for (Iterator iter = _runners.values().iterator(); iter.hasNext();) {
    96                 ClientConnectionRunner runner = (ClientConnectionRunner)iter.next();
     93        Set<ClientConnectionRunner> runners = new HashSet();
     94        synchronized (_runners) {
     95            for (Iterator<ClientConnectionRunner> iter = _runners.values().iterator(); iter.hasNext();) {
     96                ClientConnectionRunner runner = iter.next();
    9797                runners.add(runner);
    9898            }
    9999        }
    100100        synchronized (_pendingRunners) {
    101             for (Iterator iter = _pendingRunners.iterator(); iter.hasNext();) {
    102                 ClientConnectionRunner runner = (ClientConnectionRunner)iter.next();
     101            for (Iterator<ClientConnectionRunner> iter = _pendingRunners.iterator(); iter.hasNext();) {
     102                ClientConnectionRunner runner = iter.next();
    103103                runners.add(runner);
    104104            }
    105105        }
    106         for (Iterator iter = runners.iterator(); iter.hasNext(); ) {
    107             ClientConnectionRunner runner = (ClientConnectionRunner)iter.next();
     106        for (Iterator<ClientConnectionRunner> iter = runners.iterator(); iter.hasNext(); ) {
     107            ClientConnectionRunner runner = iter.next();
    108108            runner.stopRunning();
    109109        }
     
    132132    }
    133133   
     134    /**
     135     * Add to the clients list. Check for a dup destination.
     136     */
    134137    public void destinationEstablished(ClientConnectionRunner runner) {
     138        Destination dest = runner.getConfig().getDestination();
    135139        if (_log.shouldLog(Log.DEBUG))
    136             _log.debug("DestinationEstablished called for destination " + runner.getConfig().getDestination().calculateHash().toBase64());
     140            _log.debug("DestinationEstablished called for destination " + dest.calculateHash().toBase64());
    137141
    138142        synchronized (_pendingRunners) {
    139143            _pendingRunners.remove(runner);
    140144        }
    141         synchronized (_runners) {
    142             _runners.put(runner.getConfig().getDestination(), runner);
     145        boolean fail = false;
     146        synchronized (_runners) {
     147            fail = _runners.containsKey(dest);
     148            if (!fail)
     149                _runners.put(dest, runner);
     150        }
     151        if (fail) {
     152            _log.log(Log.CRIT, "Client attempted to register duplicate destination " + dest.calculateHash().toBase64());
     153            runner.disconnectClient("Duplicate destination");
    143154        }
    144155    }
     
    279290    }
    280291
    281     public Set listClients() {
    282         Set rv = new HashSet();
     292    public Set<Destination> listClients() {
     293        Set<Destination> rv = new HashSet();
    283294        synchronized (_runners) {
    284295            rv.addAll(_runners.keySet());
     
    294305        synchronized (_runners) {
    295306            inLock = _ctx.clock().now();
    296             rv = (ClientConnectionRunner)_runners.get(dest);
     307            rv = _runners.get(dest);
    297308        }
    298309        long afterLock = _ctx.clock().now();
     
    318329    /**
    319330     * Return the client's SessionKeyManager
    320      *
     331     * Use this instead of the RouterContext.sessionKeyManager()
     332     * to prevent correlation attacks across destinations
    321333     */
    322     public SessionKeyManager getClientSessionKeyManager(Destination dest) {
     334    public SessionKeyManager getClientSessionKeyManager(Hash dest) {
    323335        ClientConnectionRunner runner = getRunner(dest);
    324336        if (runner != null)
     
    332344            return null;
    333345        synchronized (_runners) {
    334             for (Iterator iter = _runners.values().iterator(); iter.hasNext(); ) {
    335                 ClientConnectionRunner cur = (ClientConnectionRunner)iter.next();
     346            for (Iterator<ClientConnectionRunner> iter = _runners.values().iterator(); iter.hasNext(); ) {
     347                ClientConnectionRunner cur = iter.next();
    336348                if (cur.getDestHash().equals(destHash))
    337349                    return cur;
     
    355367    }
    356368   
    357     Set getRunnerDestinations() {
    358         Set dests = new HashSet();
     369    Set<Destination> getRunnerDestinations() {
     370        Set<Destination> dests = new HashSet();
    359371        long beforeLock = _ctx.clock().now();
    360372        long inLock = 0;
     
    391403        buf.append("<u><b>Local destinations</b></u><br>");
    392404       
    393         Map runners = null;
     405        Map<Destination, ClientConnectionRunner> runners = null;
    394406        synchronized (_runners) {
    395407            runners = (Map)_runners.clone();
    396408        }
    397         for (Iterator iter = runners.keySet().iterator(); iter.hasNext(); ) {
    398             Destination dest = (Destination)iter.next();
    399             ClientConnectionRunner runner = (ClientConnectionRunner)runners.get(dest);
     409        for (Iterator<Destination> iter = runners.keySet().iterator(); iter.hasNext(); ) {
     410            Destination dest = iter.next();
     411            ClientConnectionRunner runner = runners.get(dest);
    400412            buf.append("<b>*</b> ").append(dest.calculateHash().toBase64().substring(0,6)).append("<br>\n");
    401413            LeaseSet ls = runner.getLeaseSet();
  • router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java

    r3a1c042c r2dd650d  
    195195     *
    196196     */
    197     public SessionKeyManager getClientSessionKeyManager(Destination dest) {
     197    public SessionKeyManager getClientSessionKeyManager(Hash dest) {
    198198        if (_manager != null)
    199199            return _manager.getClientSessionKeyManager(dest);
     
    216216     */
    217217    @Override
    218     public Set listClients() {
     218    public Set<Destination> listClients() {
    219219        if (_manager != null)
    220220            return _manager.listClients();
  • router/java/src/net/i2p/router/message/GarlicMessageBuilder.java

    r3a1c042c r2dd650d  
    1818import net.i2p.data.DataFormatException;
    1919import net.i2p.data.DataHelper;
    20 import net.i2p.data.Destination;
     20import net.i2p.data.Hash;
    2121import net.i2p.data.PublicKey;
    2222import net.i2p.data.SessionKey;
     
    6060     *  So a value somewhat higher than the low threshold
    6161     *  seems appropriate.
     62     *
     63     *  Use care when adjusting these values. See ConnectionOptions in streaming,
     64     *  and TransientSessionKeyManager in crypto, for more information.
    6265     */
    6366    private static final int DEFAULT_TAGS = 40;
    64     private static final int LOW_THRESHOLD = 20;
    65 
    66     public static int estimateAvailableTags(RouterContext ctx, PublicKey key, Destination local) {
    67         // per-dest Unimplemented
    68         //SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(local);
    69         SessionKeyManager skm = ctx.sessionKeyManager();
     67    private static final int LOW_THRESHOLD = 30;
     68
     69    /** @param local non-null; do not use this method for the router's SessionKeyManager */
     70    public static int estimateAvailableTags(RouterContext ctx, PublicKey key, Hash local) {
     71        SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(local);
    7072        if (skm == null)
    7173            return 0;
     
    7678    }
    7779   
    78     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config) {
    79         return buildMessage(ctx, config, new SessionKey(), new HashSet());
    80     }
    81 
    82     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags) {
    83         return buildMessage(ctx, config, wrappedKey, wrappedTags, DEFAULT_TAGS);
    84     }
    85 
    86     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver) {
     80    /**
     81     * Unused and probably a bad idea.
     82     *
     83     * Used below only on a recursive call if the garlic message contains a garlic message.
     84     * We don't need the SessionKey or SesssionTags returned
     85     * This uses the router's SKM, which is probably not what you want.
     86     * This isn't fully implemented, because the key and tags aren't saved - maybe
     87     * it should force elGamal?
     88     *
     89     * @param ctx scope
     90     * @param config how/what to wrap
     91     */
     92    private static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config) {
     93        Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
     94        log.error("buildMessage 2 args, using router SKM", new Exception("who did it"));
     95        return buildMessage(ctx, config, new SessionKey(), new HashSet(), ctx.sessionKeyManager());
     96    }
     97
     98    /**
     99     * called by OCMJH
     100     *
     101     * @param ctx scope
     102     * @param config how/what to wrap
     103     * @param wrappedKey output parameter that will be filled with the sessionKey used
     104     * @param wrappedTags output parameter that will be filled with the sessionTags used
     105     */
     106    public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set<SessionTag> wrappedTags,
     107                                             SessionKeyManager skm) {
     108        return buildMessage(ctx, config, wrappedKey, wrappedTags, DEFAULT_TAGS, false, skm);
     109    }
     110
     111    /** unused */
     112    /***
     113    public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags,
     114                                             int numTagsToDeliver) {
    87115        return buildMessage(ctx, config, wrappedKey, wrappedTags, numTagsToDeliver, false);
    88116    }
    89 
    90     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver, boolean forceElGamal) {
     117    ***/
     118
     119    /**
     120     * @param ctx scope
     121     * @param config how/what to wrap
     122     * @param wrappedKey output parameter that will be filled with the sessionKey used
     123     * @param wrappedTags output parameter that will be filled with the sessionTags used
     124     * @param numTagsToDeliver only if the estimated available tags are below the threshold
     125     */
     126    private static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set<SessionTag> wrappedTags,
     127                                             int numTagsToDeliver, boolean forceElGamal, SessionKeyManager skm) {
    91128        Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
    92129        PublicKey key = config.getRecipientPublicKey();
     
    105142            log.info("Encrypted with public key " + key + " to expire on " + new Date(config.getExpiration()));
    106143       
    107         SessionKey curKey = ctx.sessionKeyManager().getCurrentKey(key);
     144        SessionKey curKey = skm.getCurrentKey(key);
    108145        SessionTag curTag = null;
    109146        if (curKey == null)
    110             curKey = ctx.sessionKeyManager().createSession(key);
     147            curKey = skm.createSession(key);
    111148        if (!forceElGamal) {
    112             curTag = ctx.sessionKeyManager().consumeNextAvailableTag(key, curKey);
     149            curTag = skm.consumeNextAvailableTag(key, curKey);
    113150           
    114             int availTags = ctx.sessionKeyManager().getAvailableTags(key, curKey);
     151            int availTags = skm.getAvailableTags(key, curKey);
    115152            if (log.shouldLog(Log.DEBUG))
    116153                log.debug("Available tags for encryption to " + key + ": " + availTags);
     
    121158                if (log.shouldLog(Log.INFO))
    122159                    log.info("Too few are available (" + availTags + "), so we're including more");
    123             } else if (ctx.sessionKeyManager().getAvailableTimeLeft(key, curKey) < 60*1000) {
     160            } else if (skm.getAvailableTimeLeft(key, curKey) < 60*1000) {
    124161                // if we have enough tags, but they expire in under 30 seconds, we want more
    125162                for (int i = 0; i < numTagsToDeliver; i++)
     
    139176   
    140177    /**
     178     *  used by TestJob and directly above
     179     *
    141180     * @param ctx scope
    142181     * @param config how/what to wrap
    143      * @param wrappedKey output parameter that will be filled with the sessionKey used
     182     * @param wrappedKey unused - why??
    144183     * @param wrappedTags output parameter that will be filled with the sessionTags used
    145184     * @param target public key of the location being garlic routed to (may be null if we
     
    148187     * @param encryptTag sessionTag used to encrypt the current message
    149188     */
    150     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, PublicKey target, SessionKey encryptKey, SessionTag encryptTag) {
     189    public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set<SessionTag> wrappedTags,
     190                                             PublicKey target, SessionKey encryptKey, SessionTag encryptTag) {
    151191        Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
    152192        if (config == null)
     
    210250                    } else {
    211251                        log.debug("Subclove IS NOT a payload garlic clove");
     252                        // See notes below
    212253                        cloves[i] = buildClove(ctx, c);
    213254                    }
     
    243284    }
    244285   
     286    /**
     287     *  UNUSED
     288     *
     289     *  The Garlic Message we are building contains another garlic message,
     290     *  as specified by a GarlicConfig (NOT a PayloadGarlicConfig).
     291     *
     292     *  So this calls back to the top, to buildMessage(ctx, config),
     293     *  which uses the router's SKM, i.e. the wrong one.
     294     *  Unfortunately we've lost the reference to the SessionKeyManager way down here,
     295     *  so we can't call buildMessage(ctx, config, key, tags, skm).
     296     *
     297     *  If we do ever end up constructing a garlic message that contains a garlic message,
     298     *  we'll have to fix this by passing the skm through the last buildMessage,
     299     *  through buildCloveSet, to here.
     300     *
     301     */
    245302    private static byte[] buildClove(RouterContext ctx, GarlicConfig config) throws DataFormatException, IOException {
    246303        GarlicClove clove = new GarlicClove(ctx);
  • router/java/src/net/i2p/router/message/GarlicMessageParser.java

    r3a1c042c r2dd650d  
    1111import java.util.Date;
    1212
     13import net.i2p.crypto.SessionKeyManager;
    1314import net.i2p.data.Certificate;
    1415import net.i2p.data.DataFormatException;
     
    3334    }
    3435   
    35     public CloveSet getGarlicCloves(GarlicMessage message, PrivateKey encryptionKey) {
     36    /** @param skm use tags from this session key manager */
     37    public CloveSet getGarlicCloves(GarlicMessage message, PrivateKey encryptionKey, SessionKeyManager skm) {
    3638        byte encData[] = message.getData();
    3739        byte decrData[] = null;
     
    3941            if (_log.shouldLog(Log.DEBUG))
    4042                _log.debug("Decrypting with private key " + encryptionKey);
    41             decrData = _context.elGamalAESEngine().decrypt(encData, encryptionKey);
     43            decrData = _context.elGamalAESEngine().decrypt(encData, encryptionKey, skm);
    4244        } catch (DataFormatException dfe) {
    4345            if (_log.shouldLog(Log.WARN))
  • router/java/src/net/i2p/router/message/GarlicMessageReceiver.java

    r3a1c042c r2dd650d  
    99 */
    1010
     11import net.i2p.crypto.SessionKeyManager;
    1112import net.i2p.data.DataHelper;
    1213import net.i2p.data.Hash;
     
    4849        _parser = new GarlicMessageParser(context);
    4950        _receiver = receiver;
     51        //_log.error("New GMR dest = " + clientDestination);
    5052    }
    5153   
    5254    public void receive(GarlicMessage message) {
    5355        PrivateKey decryptionKey = null;
     56        SessionKeyManager skm = null;
    5457        if (_clientDestination != null) {
    5558            LeaseSetKeys keys = _context.keyManager().getKeys(_clientDestination);
    56             if (keys != null) {
     59            skm = _context.clientManager().getClientSessionKeyManager(_clientDestination);
     60            if (keys != null && skm != null) {
    5761                decryptionKey = keys.getDecryptionKey();
    5862            } else {
     
    6367        } else {
    6468            decryptionKey = _context.keyManager().getPrivateKey();
     69            skm = _context.sessionKeyManager();
    6570        }
    6671       
    67         CloveSet set = _parser.getGarlicCloves(message, decryptionKey);
     72        CloveSet set = _parser.getGarlicCloves(message, decryptionKey, skm);
    6873        if (set != null) {
    6974            for (int i = 0; i < set.getCloveCount(); i++) {
  • router/java/src/net/i2p/router/message/HandleGarlicMessageJob.java

    r3a1c042c r2dd650d  
    3232    private Log _log;
    3333    private GarlicMessage _message;
    34     private RouterIdentity _from;
    35     private Hash _fromHash;
    36     private Map _cloves; // map of clove Id --> Expiration of cloves we've already seen
     34    //private RouterIdentity _from;
     35    //private Hash _fromHash;
     36    //private Map _cloves; // map of clove Id --> Expiration of cloves we've already seen
    3737    //private MessageHandler _handler;
    38     private GarlicMessageParser _parser;
     38    //private GarlicMessageParser _parser;
    3939   
    4040    private final static int FORWARD_PRIORITY = 50;
    4141   
     42    /**
     43     *  @param from ignored
     44     *  @param fromHash ignored
     45     */
    4246    public HandleGarlicMessageJob(RouterContext context, GarlicMessage msg, RouterIdentity from, Hash fromHash) {
    4347        super(context);
     
    4751            _log.debug("New handle garlicMessageJob called w/ message from [" + from + "]", new Exception("Debug"));
    4852        _message = msg;
    49         _from = from;
    50         _fromHash = fromHash;
    51         _cloves = new HashMap();
     53        //_from = from;
     54        //_fromHash = fromHash;
     55        //_cloves = new HashMap();
    5256        //_handler = new MessageHandler(context);
    53         _parser = new GarlicMessageParser(context);
     57        //_parser = new GarlicMessageParser(context);
    5458    }
    5559   
  • router/java/src/net/i2p/router/message/OutboundClientMessageJobHelper.java

    r3a1c042c r2dd650d  
    1818import net.i2p.data.PublicKey;
    1919import net.i2p.data.SessionKey;
     20import net.i2p.data.SessionTag;
    2021import net.i2p.data.TunnelId;
    2122import net.i2p.data.i2np.DataMessage;
     
    4748     * For now, its just a tunneled DeliveryStatusMessage
    4849     *
     50     * Unused?
     51     *
    4952     * @param bundledReplyLeaseSet if specified, the given LeaseSet will be packaged with the message (allowing
    5053     *                             much faster replies, since their netDb search will return almost instantly)
     
    5356    static GarlicMessage createGarlicMessage(RouterContext ctx, long replyToken, long expiration, PublicKey recipientPK,
    5457                                             Payload data, Hash from, Destination dest, TunnelInfo replyTunnel,
    55                                              SessionKey wrappedKey, Set wrappedTags,
     58                                             SessionKey wrappedKey, Set<SessionTag> wrappedTags,
    5659                                             boolean requireAck, LeaseSet bundledReplyLeaseSet) {
    5760        PayloadGarlicConfig dataClove = buildDataClove(ctx, data, dest, expiration);
     
    6366     * same payload (including expiration and unique id) in different garlics (down different tunnels)
    6467     *
     68     * This is called from OCMOSJ
     69     *
    6570     * @return garlic, or null if no tunnels were found (or other errors)
    6671     */
    6772    static GarlicMessage createGarlicMessage(RouterContext ctx, long replyToken, long expiration, PublicKey recipientPK,
    6873                                             PayloadGarlicConfig dataClove, Hash from, Destination dest, TunnelInfo replyTunnel, SessionKey wrappedKey,
    69                                              Set wrappedTags, boolean requireAck, LeaseSet bundledReplyLeaseSet) {
     74                                             Set<SessionTag> wrappedTags, boolean requireAck, LeaseSet bundledReplyLeaseSet) {
    7075        GarlicConfig config = createGarlicConfig(ctx, replyToken, expiration, recipientPK, dataClove, from, dest, replyTunnel, requireAck, bundledReplyLeaseSet);
    7176        if (config == null)
    7277            return null;
    73         GarlicMessage msg = GarlicMessageBuilder.buildMessage(ctx, config, wrappedKey, wrappedTags);
     78        GarlicMessage msg = GarlicMessageBuilder.buildMessage(ctx, config, wrappedKey, wrappedTags,
     79                                                              ctx.clientManager().getClientSessionKeyManager(from));
    7480        return msg;
    7581    }
  • router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java

    r3a1c042c r2dd650d  
    1111import java.util.Set;
    1212
     13import net.i2p.crypto.SessionKeyManager;
     14import net.i2p.crypto.TagSetHandle;
    1315import net.i2p.data.Base64;
    1416import net.i2p.data.Certificate;
     
    2123import net.i2p.data.RouterInfo;
    2224import net.i2p.data.SessionKey;
     25import net.i2p.data.SessionTag;
    2326import net.i2p.data.i2cp.MessageId;
    2427import net.i2p.data.i2np.DataMessage;
     
    472475        }
    473476
    474         int existingTags = GarlicMessageBuilder.estimateAvailableTags(getContext(), _leaseSet.getEncryptionKey(), _from);
     477        int existingTags = GarlicMessageBuilder.estimateAvailableTags(getContext(), _leaseSet.getEncryptionKey(),
     478                                                                      _from.calculateHash());
    475479        _outTunnel = selectOutboundTunnel(_to);
    476480        // boolean wantACK = _wantACK || existingTags <= 30 || getContext().random().nextInt(100) < 5;
     
    490494        PublicKey key = _leaseSet.getEncryptionKey();
    491495        SessionKey sessKey = new SessionKey();
    492         Set tags = new HashSet();
     496        Set<SessionTag> tags = new HashSet();
    493497        // If we want an ack, bundle a leaseSet... (so he can get back to us)
    494498        LeaseSet replyLeaseSet = getReplyLeaseSet(wantACK);
     
    532536        ReplySelector selector = null;
    533537        if (wantACK) {
    534             onReply = new SendSuccessJob(getContext(), sessKey, tags);
    535             onFail = new SendTimeoutJob(getContext());
     538            TagSetHandle tsh = null;
     539            if ( (sessKey != null) && (tags != null) && (tags.size() > 0) ) {
     540                if (_leaseSet != null) {
     541                    SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_from.calculateHash());
     542                    if (skm != null)
     543                        tsh = skm.tagsDelivered(_leaseSet.getEncryptionKey(), sessKey, tags);
     544                }
     545            }
     546            onReply = new SendSuccessJob(getContext(), sessKey, tsh);
     547            onFail = new SendTimeoutJob(getContext(), sessKey, tsh);
    536548            selector = new ReplySelector(token);
    537549        }
     
    551563
    552564            DispatchJob dispatchJob = new DispatchJob(getContext(), msg, selector, onReply, onFail, (int)(_overallExpiration-getContext().clock().now()));
    553             if (false) // dispatch may take 100+ms, so toss it in its own job
    554                 getContext().jobQueue().addJob(dispatchJob);
    555             else
     565            //if (false) // dispatch may take 100+ms, so toss it in its own job
     566            //    getContext().jobQueue().addJob(dispatchJob);
     567            //else
    556568                dispatchJob.runJob();
    557569        } else {
     
    849861    /** build the payload clove that will be used for all of the messages, placing the clove in the status structure */
    850862    private boolean buildClove() {
     863// FIXME set SKM
    851864        PayloadGarlicConfig clove = new PayloadGarlicConfig();
    852865       
     
    933946    private class SendSuccessJob extends JobImpl implements ReplyJob {
    934947        private SessionKey _key;
    935         private Set _tags;
     948        private TagSetHandle _tags;
    936949       
    937950        /**
     
    940953         *
    941954         */
    942         public SendSuccessJob(RouterContext enclosingContext, SessionKey key, Set tags) {
     955        public SendSuccessJob(RouterContext enclosingContext, SessionKey key, TagSetHandle tags) {
    943956            super(enclosingContext);
    944957            _key = key;
     
    956969                           + " sent after " + sendTime + "ms");
    957970           
    958             if ( (_key != null) && (_tags != null) && (_tags.size() > 0) ) {
    959                 if (_leaseSet != null)
    960                     getContext().sessionKeyManager().tagsDelivered(_leaseSet.getEncryptionKey(),
    961                                                                   _key, _tags);
     971            if (_key != null && _tags != null && _leaseSet != null) {
     972                SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_from.calculateHash());
     973                if (skm != null)
     974                    skm.tagsAcked(_leaseSet.getEncryptionKey(), _key, _tags);
    962975            }
    963976           
     
    9951008     */
    9961009    private class SendTimeoutJob extends JobImpl {
    997         public SendTimeoutJob(RouterContext enclosingContext) {
     1010        private SessionKey _key;
     1011        private TagSetHandle _tags;
     1012
     1013        public SendTimeoutJob(RouterContext enclosingContext, SessionKey key, TagSetHandle tags) {
    9981014            super(enclosingContext);
     1015            _key = key;
     1016            _tags = tags;
    9991017        }
    10001018       
     
    10061024           
    10071025            _lease.setNumFailure(_lease.getNumFailure()+1);
     1026            if (_key != null && _tags != null && _leaseSet != null) {
     1027                SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_from.calculateHash());
     1028                if (skm != null)
     1029                    skm.failTags(_leaseSet.getEncryptionKey(), _key, _tags);
     1030            }
    10081031            dieFatal();
    10091032        }
  • router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java

    r3a1c042c r2dd650d  
    352352    }
    353353}
    354 
    355 /**
    356  * Try sending a search to some floodfill peers, but if we don't get a successful
    357  * match within half the allowed lookup time, give up and start querying through
    358  * the normal (kademlia) channels.  This should cut down on spurious lookups caused
    359  * by simple delays in responses from floodfill peers
    360  *
    361  */
    362 class FloodSearchJob extends JobImpl {
    363     private Log _log;
    364     private FloodfillNetworkDatabaseFacade _facade;
    365     private Hash _key;
    366     private final List _onFind;
    367     private final List _onFailed;
    368     private long _expiration;
    369     private int _timeoutMs;
    370     private long _origExpiration;
    371     private boolean _isLease;
    372     private volatile int _lookupsRemaining;
    373     private volatile boolean _dead;
    374     public FloodSearchJob(RouterContext ctx, FloodfillNetworkDatabaseFacade facade, Hash key, Job onFind, Job onFailed, int timeoutMs, boolean isLease) {
    375         super(ctx);
    376         _log = ctx.logManager().getLog(FloodSearchJob.class);
    377         _facade = facade;
    378         _key = key;
    379         _onFind = new ArrayList();
    380         _onFind.add(onFind);
    381         _onFailed = new ArrayList();
    382         _onFailed.add(onFailed);
    383         int timeout = -1;
    384         timeout = timeoutMs / FLOOD_SEARCH_TIME_FACTOR;
    385         if (timeout < timeoutMs)
    386             timeout = timeoutMs;
    387         _timeoutMs = timeout;
    388         _expiration = timeout + ctx.clock().now();
    389         _origExpiration = timeoutMs + ctx.clock().now();
    390         _isLease = isLease;
    391         _lookupsRemaining = 0;
    392         _dead = false;
    393     }
    394     void addDeferred(Job onFind, Job onFailed, long timeoutMs, boolean isLease) {
    395         if (_dead) {
    396             getContext().jobQueue().addJob(onFailed);
    397         } else {
    398             if (onFind != null) synchronized (_onFind) { _onFind.add(onFind); }
    399             if (onFailed != null) synchronized (_onFailed) { _onFailed.add(onFailed); }
    400         }
    401     }
    402     public long getExpiration() { return _expiration; }
    403     private static final int CONCURRENT_SEARCHES = 2;
    404     private static final int FLOOD_SEARCH_TIME_FACTOR = 2;
    405     private static final int FLOOD_SEARCH_TIME_MIN = 30*1000;
    406     public void runJob() {
    407         // pick some floodfill peers and send out the searches
    408         List floodfillPeers = _facade.getFloodfillPeers();
    409         FloodLookupSelector replySelector = new FloodLookupSelector(getContext(), this);
    410         ReplyJob onReply = new FloodLookupMatchJob(getContext(), this);
    411         Job onTimeout = new FloodLookupTimeoutJob(getContext(), this);
    412         OutNetMessage out = getContext().messageRegistry().registerPending(replySelector, onReply, onTimeout, _timeoutMs);
    413 
    414         for (int i = 0; _lookupsRemaining < CONCURRENT_SEARCHES && i < floodfillPeers.size(); i++) {
    415             Hash peer = (Hash)floodfillPeers.get(i);
    416             if (peer.equals(getContext().routerHash()))
    417                 continue;
    418            
    419             DatabaseLookupMessage dlm = new DatabaseLookupMessage(getContext(), true);
    420             TunnelInfo replyTunnel = getContext().tunnelManager().selectInboundTunnel();
    421             TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundTunnel();
    422             if ( (replyTunnel == null) || (outTunnel == null) ) {
    423                 _dead = true;
    424                 List removed = null;
    425                 synchronized (_onFailed) {
    426                     removed = new ArrayList(_onFailed);
    427                     _onFailed.clear();
    428                 }
    429                 while (removed.size() > 0)
    430                     getContext().jobQueue().addJob((Job)removed.remove(0));
    431                 getContext().messageRegistry().unregisterPending(out);
    432                 return;
    433             }
    434             dlm.setFrom(replyTunnel.getPeer(0));
    435             dlm.setMessageExpiration(getContext().clock().now()+10*1000);
    436             dlm.setReplyTunnel(replyTunnel.getReceiveTunnelId(0));
    437             dlm.setSearchKey(_key);
    438            
    439             if (_log.shouldLog(Log.INFO))
    440                 _log.info(getJobId() + ": Floodfill search for " + _key.toBase64() + " to " + peer.toBase64());
    441             getContext().tunnelDispatcher().dispatchOutbound(dlm, outTunnel.getSendTunnelId(0), peer);
    442             _lookupsRemaining++;
    443         }
    444        
    445         if (_lookupsRemaining <= 0) {
    446             if (_log.shouldLog(Log.INFO))
    447                 _log.info(getJobId() + ": Floodfill search for " + _key.toBase64() + " had no peers to send to");
    448             // no floodfill peers, go to the normal ones
    449             getContext().messageRegistry().unregisterPending(out);
    450             _facade.searchFull(_key, _onFind, _onFailed, _timeoutMs*FLOOD_SEARCH_TIME_FACTOR, _isLease);
    451         }
    452     }
    453     public String getName() { return "NetDb search (phase 1)"; }
    454    
    455     Hash getKey() { return _key; }
    456     void decrementRemaining() { _lookupsRemaining--; }
    457     int getLookupsRemaining() { return _lookupsRemaining; }
    458    
    459     void failed() {
    460         if (_dead) return;
    461         _dead = true;
    462         int timeRemaining = (int)(_origExpiration - getContext().clock().now());
    463         if (_log.shouldLog(Log.INFO))
    464             _log.info(getJobId() + ": Floodfill search for " + _key.toBase64() + " failed with " + timeRemaining);
    465         if (timeRemaining > 0) {
    466             _facade.searchFull(_key, _onFind, _onFailed, timeRemaining, _isLease);
    467         } else {
    468             List removed = null;
    469             synchronized (_onFailed) {
    470                 removed = new ArrayList(_onFailed);
    471                 _onFailed.clear();
    472             }
    473             while (removed.size() > 0)
    474                 getContext().jobQueue().addJob((Job)removed.remove(0));
    475         }
    476     }
    477     void success() {
    478         if (_dead) return;
    479         if (_log.shouldLog(Log.INFO))
    480             _log.info(getJobId() + ": Floodfill search for " + _key.toBase64() + " successful");
    481         _dead = true;
    482         _facade.complete(_key);
    483         List removed = null;
    484         synchronized (_onFind) {
    485             removed = new ArrayList(_onFind);
    486             _onFind.clear();
    487         }
    488         while (removed.size() > 0)
    489             getContext().jobQueue().addJob((Job)removed.remove(0));
    490     }
    491 }
    492 
    493 class FloodLookupTimeoutJob extends JobImpl {
    494     private FloodSearchJob _search;
    495     public FloodLookupTimeoutJob(RouterContext ctx, FloodSearchJob job) {
    496         super(ctx);
    497         _search = job;
    498     }
    499     public void runJob() {
    500         _search.decrementRemaining();
    501         if (_search.getLookupsRemaining() <= 0)
    502             _search.failed();
    503     }
    504     public String getName() { return "NetDb search (phase 1) timeout"; }
    505 }
    506 
    507 class FloodLookupMatchJob extends JobImpl implements ReplyJob {
    508     private Log _log;
    509     private FloodSearchJob _search;
    510     public FloodLookupMatchJob(RouterContext ctx, FloodSearchJob job) {
    511         super(ctx);
    512         _log = ctx.logManager().getLog(FloodLookupMatchJob.class);
    513         _search = job;
    514     }
    515     public void runJob() {
    516         if ( (getContext().netDb().lookupLeaseSetLocally(_search.getKey()) != null) ||
    517              (getContext().netDb().lookupRouterInfoLocally(_search.getKey()) != null) ) {
    518             _search.success();
    519         } else {
    520             int remaining = _search.getLookupsRemaining();
    521             if (_log.shouldLog(Log.INFO))
    522                 _log.info(getJobId() + "/" + _search.getJobId() + ": got a reply looking for "
    523                           + _search.getKey().toBase64() + ", with " + remaining + " outstanding searches");
    524             // netDb reply pointing us at other people
    525             if (remaining <= 0)
    526                 _search.failed();
    527         }
    528     }
    529     public String getName() { return "NetDb search (phase 1) match"; }
    530     public void setMessage(I2NPMessage message) {}
    531 }
    532 
    533 class FloodLookupSelector implements MessageSelector {
    534     private RouterContext _context;
    535     private FloodSearchJob _search;
    536     public FloodLookupSelector(RouterContext ctx, FloodSearchJob search) {
    537         _context = ctx;
    538         _search = search;
    539     }
    540     public boolean continueMatching() { return _search.getLookupsRemaining() > 0; }
    541     public long getExpiration() { return _search.getExpiration(); }
    542     public boolean isMatch(I2NPMessage message) {
    543         if (message == null) return false;
    544         if (message instanceof DatabaseStoreMessage) {
    545             DatabaseStoreMessage dsm = (DatabaseStoreMessage)message;
    546             // is it worth making sure the reply came in on the right tunnel?
    547             if (_search.getKey().equals(dsm.getKey())) {
    548                 _search.decrementRemaining();
    549                 return true;
    550             }
    551         } else if (message instanceof DatabaseSearchReplyMessage) {
    552             DatabaseSearchReplyMessage dsrm = (DatabaseSearchReplyMessage)message;
    553             if (_search.getKey().equals(dsrm.getSearchKey())) {
    554                 _search.decrementRemaining();
    555                 return true;
    556             }
    557         }
    558         return false;
    559     }   
    560 }
  • router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java

    r3a1c042c r2dd650d  
    10041004        out.write("<h2>Network Database Contents (<a href=\"netdb.jsp?l=1\">View LeaseSets</a>)</h2>\n");
    10051005        if (!_initialized) {
    1006             buf.append("<i>Not initialized</i>\n");
     1006            buf.append("Not initialized\n");
    10071007            out.write(buf.toString());
    10081008            out.flush();
     
    10531053            for (String routerVersion : versionList) {
    10541054                int num = versions.count(routerVersion);
    1055                 buf.append("<tr><td>").append(DataHelper.stripHTML(routerVersion));
    1056                 buf.append("</td><td align=\"right\">").append(num).append("</td></tr>\n");
     1055                buf.append("<tr><td align=\"center\">").append(DataHelper.stripHTML(routerVersion));
     1056                buf.append("</td><td align=\"center\">").append(num).append("</td></tr>\n");
    10571057            }
    10581058            buf.append("</table>\n");
     
    10721072                buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> ");
    10731073                buf.append(_context.commSystem().getCountryName(country));
    1074                 buf.append("</td><td align=\"right\">").append(num).append("</td></tr>\n");
     1074                buf.append("</td><td align=\"center\">").append(num).append("</td></tr>\n");
    10751075            }
    10761076            buf.append("</table>\n");
     
    10871087    private void renderRouterInfo(StringBuilder buf, RouterInfo info, boolean isUs, boolean full) {
    10881088        String hash = info.getIdentity().getHash().toBase64();
    1089         buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
     1089        buf.append("<table><tr><th><a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
    10901090        if (isUs) {
    1091             buf.append("<a name=\"our-info\" ></a><b>Our info: ").append(hash).append("</b><br>\n");
     1091            buf.append("<a name=\"our-info\" ></a><b>Our info: ").append(hash).append("</b></th></tr><tr><td>\n");
    10921092        } else {
    1093             buf.append("<b>Peer info for:</b> ").append(hash).append("<br>\n");
     1093            buf.append("<b>Peer info for:</b> ").append(hash).append("\n");
     1094            if (full) {
     1095                buf.append("[<a href=\"netdb.jsp\" >Back</a>]</th></tr><td>\n");
     1096            } else {
     1097                buf.append("[<a href=\"netdb.jsp?r=").append(hash.substring(0, 6)).append("\" >Full entry</a>]</th></tr><td>\n");
     1098            }
    10941099        }
    10951100       
    10961101        long age = _context.clock().now() - info.getPublished();
    10971102        if (isUs && _context.router().isHidden())
    1098             buf.append("Hidden, Updated: <i>").append(DataHelper.formatDuration(age)).append(" ago</i><br>\n");
     1103            buf.append("<b>Hidden, Updated:</b> ").append(DataHelper.formatDuration(age)).append(" ago<br>\n");
    10991104        else if (age > 0)
    1100             buf.append("Published: <i>").append(DataHelper.formatDuration(age)).append(" ago</i><br>\n");
     1105            buf.append("<b>Published:</b> ").append(DataHelper.formatDuration(age)).append(" ago<br>\n");
    11011106        else
    1102             buf.append("Published: <i>in ").append(DataHelper.formatDuration(0-age)).append("???</i><br>\n");
    1103         buf.append("Address(es): <i>");
     1107            buf.append("<b>Published:</b> in ").append(DataHelper.formatDuration(0-age)).append("???<br>\n");
     1108        buf.append("<b>Address(es):</b> ");
    11041109        String country = _context.commSystem().getCountry(info.getIdentity().getHash());
    11051110        if(country != null) {
     
    11161121            }
    11171122        }
    1118         buf.append("</i><br>\n");
     1123        buf.append("</td></tr>\n");
    11191124        if (full) {
    1120             buf.append("Stats: <br><i><code>\n");
     1125            buf.append("<tr><td>Stats: <br><code>\n");
    11211126            for (Iterator iter = info.getOptions().keySet().iterator(); iter.hasNext(); ) {
    11221127                String key = (String)iter.next();
     
    11241129                buf.append(DataHelper.stripHTML(key)).append(" = ").append(DataHelper.stripHTML(val)).append("<br>\n");
    11251130            }
    1126             buf.append("</code></i>\n");
     1131            buf.append("</code></td></tr>\n");
    11271132        } else {
    1128             buf.append("<a href=\"netdb.jsp?r=").append(hash.substring(0, 6)).append("\" >Full entry</a>\n");
    1129         }
    1130         buf.append("<hr>\n");
    1131     }
    1132    
     1133        }
     1134        buf.append("</td></tr>\n");
     1135    }
     1136
    11331137}
  • router/java/src/net/i2p/router/tunnel/pool/TestJob.java

    r3a1c042c r2dd650d  
    44import java.util.Set;
    55
     6import net.i2p.crypto.SessionKeyManager;
    67import net.i2p.data.Certificate;
    78import net.i2p.data.SessionKey;
     
    2930    private TunnelInfo _replyTunnel;
    3031    private PooledTunnelCreatorConfig _otherTunnel;
     32    /** save this so we can tell the SKM to kill it if the test fails */
     33    private SessionTag _encryptTag;
    3134   
    3235    /** base to randomize the test delay on */
     
    130133        SessionKey encryptKey = getContext().keyGenerator().generateSessionKey();
    131134        SessionTag encryptTag = new SessionTag(true);
     135        _encryptTag = encryptTag;
    132136        SessionKey sentKey = new SessionKey();
    133137        Set sentTags = null;
     
    143147        Set encryptTags = new HashSet(1);
    144148        encryptTags.add(encryptTag);
    145         getContext().sessionKeyManager().tagsReceived(encryptKey, encryptTags);
     149        // Register the single tag with the appropriate SKM
     150        if (_cfg.isInbound() && !_pool.getSettings().isExploratory()) {
     151            SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_pool.getSettings().getDestination());
     152            if (skm != null)
     153                skm.tagsReceived(encryptKey, encryptTags);
     154        } else {
     155            getContext().sessionKeyManager().tagsReceived(encryptKey, encryptTags);
     156        }
    146157
    147158        if (_log.shouldLog(Log.DEBUG))
     
    308319            if (_log.shouldLog(Log.WARN))
    309320                _log.warn("Timeout: found? " + _found, getAddedBy());
    310             if (!_found)
     321            if (!_found) {
     322                // don't clog up the SKM with old one-tag tagsets
     323                if (_cfg.isInbound() && !_pool.getSettings().isExploratory()) {
     324                    SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_pool.getSettings().getDestination());
     325                    if (skm != null)
     326                        skm.consumeTag(_encryptTag);
     327                } else {
     328                    getContext().sessionKeyManager().consumeTag(_encryptTag);
     329                }
    311330                testFailed(getContext().clock().now() - _started);
     331            }
    312332        }
    313333       
  • router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java

    r3a1c042c r2dd650d  
    310310        //buildComplete();
    311311        if (cfg.getLength() > 1 &&
    312             !_context.router().gracefulShutdownInProgress()) {
     312            (!_context.router().gracefulShutdownInProgress()) &&
     313            !Boolean.valueOf(_context.getProperty("router.disableTunnelTesting")).booleanValue()) {
    313314            TunnelPool pool = cfg.getTunnelPool();
    314315            if (pool == null) {
Note: See TracChangeset for help on using the changeset viewer.