Changeset e0f1047


Ignore:
Timestamp:
Aug 30, 2009 4:27:03 PM (11 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
1571907
Parents:
15f0cda
Message:
  • SessionKeyManager?, OCMOSJ, Garlic:
    • Enable per-client SessionKeyManagers? for better anonymity
    • tagsDelivered() now means tags are sent, not acked.
    • OCMOSJ uses the new TagSetHandle? object returned from tagsDelivered() to call tagsAcked() or failTags() as appropriate.
    • Assume tags delivered on an established session to reduce streaming lib stalls caused by massive tag deliveries; should increase throughput and window sizes on long-lived streams
    • Unacked tagsets on a new session are stored on a separate list
    • Don't kill an OB Session just because it's temporarily out of tags
    • Increase min tag threshold to 30 (was 20) due to new speculative tags delivered scheme, and to increase effective max window
    • More Java 5 and dead code cleanups, and more comments and javadoc, debug logging cleanups
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/crypto/SessionKeyManager.java

    r15f0cda re0f1047  
    9696     *
    9797     */
    98     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;
    99100    }
    100101
     
    135136
    136137    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) {}
    137140}
  • core/java/src/net/i2p/crypto/TransientSessionKeyManager.java

    r15f0cda re0f1047  
    2020import java.util.List;
    2121import java.util.Map;
     22import java.util.NoSuchElementException;
    2223import java.util.Set;
    2324import java.util.TreeSet;
     
    3637 * to disk).  However, this being java, we cannot guarantee that the keys aren't swapped
    3738 * 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 * A second consecutive TagSet delivery failure will cause a complete stall, as
     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
    3874 *
    3975 */
     
    127163
    128164    /* FIXME Exporting non-public type through public API */
     165/****** leftover from when we had the persistent SKM
    129166    protected void setData(Set<TagSet> inboundTagSets, Set<OutboundSession> outboundSessions) {
    130167        if (_log.shouldLog(Log.INFO))
     
    153190        }
    154191    }
     192******/
    155193
    156194    /**
     
    180218     * when to expire that key begin with this call.
    181219     *
    182      * Unused except in tests?
    183220     */
    184221    @Override
    185222    public void createSession(PublicKey target, SessionKey key) {
    186         OutboundSession sess = new OutboundSession(target);
    187         sess.setCurrentKey(key);
    188         addSession(sess);
     223        createAndReturnSession(target, key);
    189224    }
    190225
     
    219254            SessionTag nxt = sess.consumeNext();
    220255            if (_log.shouldLog(Log.DEBUG))
    221                 _log.debug("Tag consumed: " + nxt + " with key: " + key.toBase64());
     256                _log.debug("OB Tag consumed: " + nxt + " with: " + key);
    222257            return nxt;
    223258        }
     
    262297    /**
    263298     * Take note of the fact that the given sessionTags associated with the key for
    264      * encryption to the target have definitely been received at the target (aka call this
    265      * method after receiving an ack to a message delivering them)
    266      *
    267      */
    268     @Override
    269     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) {
    270311        if (_log.shouldLog(Log.DEBUG)) {
    271312            //_log.debug("Tags delivered to set " + set + " on session " + sess);
    272313            if (sessionTags.size() > 0)
    273                 _log.debug("Tags delivered: " + sessionTags.size() + " for key: " + key.toBase64() + ": " + sessionTags);
     314                _log.debug("Tags delivered: " + sessionTags.size() + " for key: " + key + ": " + sessionTags);
    274315        }
    275316        OutboundSession sess = getSession(target);
    276317        if (sess == null)
    277318            sess = createAndReturnSession(target, key);
    278         sess.setCurrentKey(key);
     319        else
     320            sess.setCurrentKey(key);
    279321        TagSet set = new TagSet(sessionTags, key, _context.clock().now());
    280322        sess.addTags(set);
     323        return set;
    281324    }
    282325
     
    286329     * from corrupted tag sets and crashes
    287330     *
     331     * @deprecated unused and rather drastic
    288332     */
    289333    @Override
    290334    public void failTags(PublicKey target) {
    291335        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);
    292367    }
    293368
     
    305380            SessionTag tag = iter.next();
    306381            if (_log.shouldLog(Log.DEBUG))
    307                 _log.debug("Receiving tag " + tag + " for key " + key.toBase64() + " / " + key.toString() + ": tagSet: " + tagSet);
     382                _log.debug("Receiving tag " + tag + " for key " + key + ": tagSet: " + tagSet);
    308383            synchronized (_inboundTagSets) {
    309                 old = (TagSet)_inboundTagSets.put(tag, tagSet);
     384                old = _inboundTagSets.put(tag, tagSet);
    310385                overage = _inboundTagSets.size() - MAX_INBOUND_SESSION_TAGS;
    311386                if (old != null) {
     
    335410
    336411            if (_log.shouldLog(Log.WARN)) {
    337                 _log.warn("Multiple tags matching!  tagSet: " + tagSet + " and old tagSet: " + old + " tag: " + dupTag + "/" + dupTag.toBase64());
    338                 _log.warn("Earlier tag set creation: " + old + ": key=" + old.getAssociatedKey().toBase64(), old.getCreatedBy());
    339                 _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());
    340415            }
    341416        }
     
    411486    @Override
    412487    public SessionKey consumeTag(SessionTag tag) {
    413         if (false) aggressiveExpire();
     488        //if (false) aggressiveExpire();
    414489        synchronized (_inboundTagSets) {
    415490            TagSet tagSet = (TagSet) _inboundTagSets.remove(tag);
    416491            if (tagSet == null) {
    417492                if (_log.shouldLog(Log.DEBUG))
    418                     _log.debug("Cannot consume tag " + tag + " as it is not known");
     493                    _log.debug("Cannot consume IB " + tag + " as it is not known");
    419494                return null;
    420495            }
     
    423498            SessionKey key = tagSet.getAssociatedKey();
    424499            if (_log.shouldLog(Log.DEBUG))
    425                 _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);
    426501            return key;
    427502        }
     
    430505    private OutboundSession getSession(PublicKey target) {
    431506        synchronized (_outboundSessions) {
    432             return (OutboundSession) _outboundSessions.get(target);
     507            return _outboundSessions.get(target);
    433508        }
    434509    }
     
    444519        OutboundSession session = null;
    445520        synchronized (_outboundSessions) {
    446             session = (OutboundSession)_outboundSessions.remove(target);
     521            session = _outboundSessions.remove(target);
    447522        }
    448523        if ( (session != null) && (_log.shouldLog(Log.WARN)) )
     
    462537        long now = _context.clock().now();
    463538        StringBuilder buf = null;
    464         StringBuilder bufSummary = null;
     539        //StringBuilder bufSummary = null;
    465540        if (_log.shouldLog(Log.DEBUG)) {
    466541            buf = new StringBuilder(128);
    467542            buf.append("Expiring inbound: ");
    468             bufSummary = new StringBuilder(1024);
     543            //bufSummary = new StringBuilder(1024);
    469544        }
    470545        synchronized (_inboundTagSets) {
     
    478553                    removed++;
    479554                    if (buf != null)
    480                         buf.append(tag.toString()).append(" @ age ").append(DataHelper.formatDuration(age));
    481                 } else if (false && (bufSummary != null) ) {
    482                     bufSummary.append("\nTagSet: " + ts.toString() + ", key: " + ts.getAssociatedKey().toBase64()+"/" + ts.getAssociatedKey().toString()
    483                                       + ": 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);
    484559                }
    485560            }
     
    489564        if ( (buf != null) && (removed > 0) )
    490565            _log.debug(buf.toString());
    491         if (bufSummary != null)
    492             _log.debug("Cleaning up with remaining: " + bufSummary.toString());
     566        //if (bufSummary != null)
     567        //    _log.debug("Cleaning up with remaining: " + bufSummary.toString());
    493568
    494569        //_log.warn("Expiring tags: [" + tagsToDrop + "]");
     
    499574                OutboundSession sess = _outboundSessions.get(key);
    500575                removed += sess.expireTags();
    501                 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) {
    502579                    iter.remove();
    503                     removed++;
     580                    removed++;   // just to have a non-zero return value?
    504581                }
    505582            }
     
    564641                total += size;
    565642                buf.append("<li><b>Sent:</b> ").append(DataHelper.formatDuration(now - ts.getDate())).append(" ago with ");
    566                 buf.append(size).append(" tags remaining</li>");
     643                buf.append(size).append(" tags remaining; acked? ").append(ts.getAcked()).append("</li>");
    567644            }
    568645            buf.append("</ul></td></tr>\n");
     
    581658     *  Earliest first
    582659     */
    583     private class TagSetComparator implements Comparator {
     660    private static class TagSetComparator implements Comparator {
    584661         public int compare(Object l, Object r) {
    585662             return (int) (((TagSet)l).getDate() - ((TagSet)r).getDate());
     
    587664    }
    588665
    589     class OutboundSession {
     666    private class OutboundSession {
    590667        private PublicKey _target;
    591668        private SessionKey _currentKey;
    592669        private long _established;
    593670        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         */
    594678        private /* FIXME final FIXME */ List<TagSet> _tagSets;
     679        /** set to true after first tagset is acked */
     680        private boolean _acked;
    595681
    596682        public OutboundSession(PublicKey target) {
     
    603689            _established = established;
    604690            _lastUsed = lastUsed;
    605             _tagSets = tagSets;
    606         }
    607 
    608         /** 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         */
    609700        List<TagSet> getTagSets() {
     701            List<TagSet> rv;
     702            synchronized (_unackedTagSets) {
     703                rv = new ArrayList(_unackedTagSets);
     704            }
    610705            synchronized (_tagSets) {
    611                 return new ArrayList(_tagSets);
    612             }
     706                rv.addAll(_tagSets);
     707            }
     708            return rv;
     709        }
     710
     711        /**
     712         *  got an ack for these tags
     713         *  For tagsets delivered after the session was acked, this is a nop
     714         *  because the tagset was originally placed directly on the acked list.
     715         */
     716        void ackTags(TagSet set) {
     717            if (_unackedTagSets.remove(set)) {
     718                _tagSets.add(set);
     719                _acked = true;
     720            }
     721            set.setAcked();
     722        }
     723
     724        /** didn't get an ack for these tags */
     725        void failTags(TagSet set) {
     726            _unackedTagSets.remove(set);
     727            _tagSets.remove(set);
    613728        }
    614729
     
    657772            synchronized (_tagSets) {
    658773                for (int i = 0; i < _tagSets.size(); i++) {
    659                     TagSet set = (TagSet) _tagSets.get(i);
     774                    TagSet set = _tagSets.get(i);
    660775                    if (set.getDate() + SESSION_TAG_DURATION_MS <= now) {
    661776                        _tagSets.remove(i);
     
    673788            synchronized (_tagSets) {
    674789                while (_tagSets.size() > 0) {
    675                     TagSet set = (TagSet) _tagSets.get(0);
     790                    TagSet set = _tagSets.get(0);
    676791                    if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
    677792                        SessionTag tag = set.consumeNext();
     
    687802        }
    688803
     804        /** @return the total number of tags in acked TagSets */
    689805        public int availableTags() {
    690806            int tags = 0;
     
    692808            synchronized (_tagSets) {
    693809                for (int i = 0; i < _tagSets.size(); i++) {
    694                     TagSet set = (TagSet) _tagSets.get(i);
     810                    TagSet set = _tagSets.get(i);
    695811                    if (set.getDate() + SESSION_TAG_DURATION_MS > now)
    696812                        tags += set.getTags().size();
     
    720836        }
    721837
     838        /**
     839         *  If the session has never been acked, put the TagSet on the unacked list.
     840         *  Otherwise, consider it good right away.
     841         */
    722842        public void addTags(TagSet set) {
    723843            _lastUsed = _context.clock().now();
    724             synchronized (_tagSets) {
    725                 _tagSets.add(set);
    726             }
    727         }
    728     }
    729 
    730     static class TagSet {
     844            if (_acked) {
     845                synchronized (_tagSets) {
     846                    _tagSets.add(set);
     847                }
     848            } else {
     849                synchronized (_unackedTagSets) {
     850                    _unackedTagSets.add(set);
     851                }
     852            }
     853        }
     854    }
     855
     856    private static class TagSet implements TagSetHandle {
    731857        private Set<SessionTag> _sessionTags;
    732858        private SessionKey _key;
    733859        private long _date;
    734         private Exception _createdBy;
     860        //private Exception _createdBy;
     861        /** only used in renderStatusHTML() for debugging */
     862        private boolean _acked;
    735863
    736864        public TagSet(Set<SessionTag> tags, SessionKey key, long date) {
     
    740868            _key = key;
    741869            _date = date;
    742             if (true) {
    743                 long now = I2PAppContext.getGlobalContext().clock().now();
    744                 _createdBy = new Exception("Created by: key=" + _key.toBase64() + " on "
    745                                            + new Date(now) + "/" + now
    746                                            + " via " + Thread.currentThread().getName());
    747             }
     870            //if (true) {
     871            //    long now = I2PAppContext.getGlobalContext().clock().now();
     872            //    _createdBy = new Exception("Created by: key=" + _key.toBase64() + " on "
     873            //                               + new Date(now) + "/" + now
     874            //                               + " via " + Thread.currentThread().getName());
     875            //}
    748876        }
    749877
     
    771899
    772900        public void consume(SessionTag tag) {
    773             if (contains(tag)) {
    774                 _sessionTags.remove(tag);
    775             }
    776         }
    777 
     901            _sessionTags.remove(tag);
     902        }
     903
     904        /** let's do this without counting the elements first */
    778905        public SessionTag consumeNext() {
    779             if (_sessionTags.size() <= 0) {
     906            SessionTag first;
     907            try {
     908                first = _sessionTags.iterator().next();
     909            } catch (NoSuchElementException nsee) {
    780910                return null;
    781911            }
    782 
    783             SessionTag first = (SessionTag) _sessionTags.iterator().next();
    784912            _sessionTags.remove(first);
    785913            return first;
    786914        }
    787915       
    788         public Exception getCreatedBy() { return _createdBy; }
     916        //public Exception getCreatedBy() { return _createdBy; }
     917
     918        public void setAcked() { _acked = true; }
     919        /** only used in renderStatusHTML() for debugging */
     920        public boolean getAcked() { return _acked; }
    789921       
    790922        @Override
     
    801933            if ((o == null) || !(o instanceof TagSet)) return false;
    802934            TagSet ts = (TagSet) o;
    803             return DataHelper.eq(ts.getAssociatedKey(), getAssociatedKey())
     935            return DataHelper.eq(ts.getAssociatedKey(), _key)
    804936                   //&& DataHelper.eq(ts.getTags(), getTags())
    805                    && ts.getDate() == getDate();
     937                   && ts.getDate() == _date;
     938        }
     939
     940        @Override
     941        public String toString() {
     942            StringBuilder buf = new StringBuilder(256);
     943            buf.append("TagSet established: ").append(new Date(_date));
     944            buf.append(" Session key: ").append(_key.toBase64());
     945            buf.append(" Size: ").append(_sessionTags.size());
     946            buf.append(" Acked? ").append(_acked);
     947            return buf.toString();
    806948        }
    807949    }
  • router/java/src/net/i2p/router/message/GarlicMessageBuilder.java

    r15f0cda re0f1047  
    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

    r15f0cda re0f1047  
    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

    r15f0cda re0f1047  
    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/OutboundClientMessageJobHelper.java

    r15f0cda re0f1047  
    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

    r15f0cda re0f1047  
    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        }
Note: See TracChangeset for help on using the changeset viewer.