From 22609bbfdb94c6a60d3b26d1ffcf4f7f1eb9f78c Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Fri, 29 May 2009 13:57:50 +0000
Subject: [PATCH]     * SessionKeyManager:       - More stubs for
 per-destination managers.         No functional changes yet.

---
 .../i2p/crypto/TransientSessionKeyManager.java | 18 +++++++++++++++++-
 .../net/i2p/router/ClientManagerFacade.java    |  2 ++
 .../i2p/router/DummyClientManagerFacade.java   |  2 ++
 .../router/client/ClientConnectionRunner.java  | 13 +++++++++++++
 .../net/i2p/router/client/ClientManager.java   | 13 +++++++++++++
 .../router/client/ClientManagerFacadeImpl.java | 14 ++++++++++++++
 .../router/message/GarlicMessageBuilder.java   | 16 +++++++++++++---
 .../OutboundClientMessageOneShotJob.java       |  2 +-
 8 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
index 7c496c62d0..9bda56119f 100644
--- a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
+++ b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
@@ -40,6 +40,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
     /** Map allowing us to go from a SessionTag to the containing TagSet */
     private Map<SessionTag, TagSet> _inboundTagSets;
     protected I2PAppContext _context;
+    private volatile boolean _alive;
 
     /** 
      * Let session tags sit around for 10 minutes before expiring them.  We can now have such a large
@@ -75,19 +76,34 @@ public class TransientSessionKeyManager extends SessionKeyManager {
         _inboundTagSets = new HashMap(1024);
         context.statManager().createRateStat("crypto.sessionTagsExpired", "How many tags/sessions are expired?", "Encryption", new long[] { 10*60*1000, 60*60*1000, 3*60*60*1000 });
         context.statManager().createRateStat("crypto.sessionTagsRemaining", "How many tags/sessions are remaining after a cleanup?", "Encryption", new long[] { 10*60*1000, 60*60*1000, 3*60*60*1000 });
-        SimpleScheduler.getInstance().addPeriodicEvent(new CleanupEvent(), 60*1000);
+         _alive = true;
+        SimpleScheduler.getInstance().addEvent(new CleanupEvent(), 60*1000);
     }
     private TransientSessionKeyManager() { this(null); }
     
+    public void shutdown() {
+         _alive = false;
+        synchronized (_inboundTagSets) {
+            _inboundTagSets.clear();
+        }
+        synchronized (_outboundSessions) {
+            _outboundSessions.clear();
+        }
+    }
+
     private class CleanupEvent implements SimpleTimer.TimedEvent {
         public void timeReached() {
+            if (!_alive)
+                return;
             long beforeExpire = _context.clock().now();
             int expired = aggressiveExpire();
             long expireTime = _context.clock().now() - beforeExpire;
             _context.statManager().addRateData("crypto.sessionTagsExpired", expired, expireTime);
+            SimpleScheduler.getInstance().addEvent(this, 60*1000);
         }
     }
 
+
     /** TagSet */
     protected Set<TagSet> getInboundTagSets() {
         synchronized (_inboundTagSets) {
diff --git a/router/java/src/net/i2p/router/ClientManagerFacade.java b/router/java/src/net/i2p/router/ClientManagerFacade.java
index 2e441fefe2..0ce20df6ad 100644
--- a/router/java/src/net/i2p/router/ClientManagerFacade.java
+++ b/router/java/src/net/i2p/router/ClientManagerFacade.java
@@ -13,6 +13,7 @@ import java.io.Writer;
 import java.util.Collections;
 import java.util.Set;
 
+import net.i2p.crypto.SessionKeyManager;
 import net.i2p.data.Destination;
 import net.i2p.data.Hash;
 import net.i2p.data.LeaseSet;
@@ -91,5 +92,6 @@ public abstract class ClientManagerFacade implements Service {
      *
      */
     public abstract SessionConfig getClientSessionConfig(Destination dest);
+    public abstract SessionKeyManager getClientSessionKeyManager(Destination dest);
     public void renderStatusHTML(Writer out) throws IOException { }
 }
diff --git a/router/java/src/net/i2p/router/DummyClientManagerFacade.java b/router/java/src/net/i2p/router/DummyClientManagerFacade.java
index 61e312875b..5e362e3ddb 100644
--- a/router/java/src/net/i2p/router/DummyClientManagerFacade.java
+++ b/router/java/src/net/i2p/router/DummyClientManagerFacade.java
@@ -8,6 +8,7 @@ package net.i2p.router;
  *
  */
 
+import net.i2p.crypto.SessionKeyManager;
 import net.i2p.data.Destination;
 import net.i2p.data.Hash;
 import net.i2p.data.LeaseSet;
@@ -40,6 +41,7 @@ public class DummyClientManagerFacade extends ClientManagerFacade {
     public void messageDeliveryStatusUpdate(Destination fromDest, MessageId id, boolean delivered) {}
     
     public SessionConfig getClientSessionConfig(Destination _dest) { return null; }
+    public SessionKeyManager getClientSessionKeyManager(Destination _dest) { return null; }
     
     public void requestLeaseSet(Hash dest, LeaseSet set) {}
     
diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
index 5611f13774..a084bafce6 100644
--- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
+++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
@@ -17,6 +17,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import net.i2p.crypto.SessionKeyManager;
+import net.i2p.crypto.TransientSessionKeyManager;
 import net.i2p.data.Destination;
 import net.i2p.data.Hash;
 import net.i2p.data.LeaseSet;
@@ -68,6 +70,8 @@ public class ClientConnectionRunner {
     private Set<MessageId> _acceptedPending;
     /** thingy that does stuff */
     private I2CPMessageReader _reader;
+    /** just for this destination */
+    private SessionKeyManager _sessionKeyManager;
     /** 
      * This contains the last 10 MessageIds that have had their (non-ack) status 
      * delivered to the client (so that we can be sure only to update when necessary)
@@ -129,6 +133,8 @@ public class ClientConnectionRunner {
         if (_writer != null) _writer.stopWriting();
         if (_socket != null) try { _socket.close(); } catch (IOException ioe) { }
         _messages.clear();
+        if (_sessionKeyManager != null)
+            _sessionKeyManager.shutdown();
         if (_manager != null)
             _manager.unregisterConnection(this);
         if (_currentLeaseSet != null)
@@ -143,6 +149,8 @@ public class ClientConnectionRunner {
     
     /** current client's config */
     public SessionConfig getConfig() { return _config; }
+    /** current client's sessionkeymanager */
+    public SessionKeyManager getSessionKeyManager() { return _sessionKeyManager; }
     /** currently allocated leaseSet */
     public LeaseSet getLeaseSet() { return _currentLeaseSet; }
     void setLeaseSet(LeaseSet ls) { _currentLeaseSet = ls; }
@@ -181,6 +189,11 @@ public class ClientConnectionRunner {
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("SessionEstablished called for destination " + _destHashCache.toBase64());
         _config = config;
+        // per-dest unimplemented
+        //if (_sessionKeyManager == null)
+        //    _sessionKeyManager = new TransientSessionKeyManager(_context);
+        //else
+        //    _log.error("SessionEstablished called for twice for destination " + _destHashCache.toBase64().substring(0,4));
         _manager.destinationEstablished(this);
     }
     
diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java
index 85e7d9ec76..e58f16b262 100644
--- a/router/java/src/net/i2p/router/client/ClientManager.java
+++ b/router/java/src/net/i2p/router/client/ClientManager.java
@@ -16,6 +16,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import net.i2p.crypto.SessionKeyManager;
 import net.i2p.data.DataHelper;
 import net.i2p.data.Destination;
 import net.i2p.data.Hash;
@@ -314,6 +315,18 @@ public class ClientManager {
             return null;
     }
     
+    /**
+     * Return the client's SessionKeyManager
+     *
+     */
+    public SessionKeyManager getClientSessionKeyManager(Destination dest) {
+        ClientConnectionRunner runner = getRunner(dest);
+        if (runner != null)
+            return runner.getSessionKeyManager();
+        else
+            return null;
+    }
+    
     private ClientConnectionRunner getRunner(Hash destHash) {
         if (destHash == null) 
             return null;
diff --git a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java
index eddf13dd8e..543b5e29c4 100644
--- a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java
+++ b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java
@@ -14,6 +14,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.Set;
 
+import net.i2p.crypto.SessionKeyManager;
 import net.i2p.data.DataHelper;
 import net.i2p.data.Destination;
 import net.i2p.data.Hash;
@@ -199,6 +200,19 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade {
         }
     }
     
+    /**
+     * Return the client's current manager or null if not connected
+     *
+     */
+    public SessionKeyManager getClientSessionKeyManager(Destination dest) {
+        if (_manager != null)
+            return _manager.getClientSessionKeyManager(dest);
+        else {
+            _log.error("Null manager on getClientSessionKeyManager!");
+            return null;
+        }
+    }
+    
     @Override
     public void renderStatusHTML(Writer out) throws IOException { 
         if (_manager != null)
diff --git a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java
index 2a04de8e4e..a049b7b8cd 100644
--- a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java
+++ b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java
@@ -14,8 +14,10 @@ import java.util.Date;
 import java.util.HashSet;
 import java.util.Set;
 
+import net.i2p.crypto.SessionKeyManager;
 import net.i2p.data.DataFormatException;
 import net.i2p.data.DataHelper;
+import net.i2p.data.Destination;
 import net.i2p.data.PublicKey;
 import net.i2p.data.SessionKey;
 import net.i2p.data.SessionTag;
@@ -61,22 +63,30 @@ public class GarlicMessageBuilder {
     private static final int DEFAULT_TAGS = 40;
     private static final int LOW_THRESHOLD = 20;
 
-    public static int estimateAvailableTags(RouterContext ctx, PublicKey key) {
-        SessionKey curKey = ctx.sessionKeyManager().getCurrentKey(key);
+    public static int estimateAvailableTags(RouterContext ctx, PublicKey key, Destination local) {
+        // per-dest Unimplemented
+        //SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(local);
+        SessionKeyManager skm = ctx.sessionKeyManager();
+        if (skm == null)
+            return 0;
+        SessionKey curKey = skm.getCurrentKey(key);
         if (curKey == null)
             return 0;
-        return ctx.sessionKeyManager().getAvailableTags(key, curKey);
+        return skm.getAvailableTags(key, curKey);
     }
     
     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config) {
         return buildMessage(ctx, config, new SessionKey(), new HashSet());
     }
+
     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags) {
         return buildMessage(ctx, config, wrappedKey, wrappedTags, DEFAULT_TAGS);
     }
+
     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver) {
         return buildMessage(ctx, config, wrappedKey, wrappedTags, numTagsToDeliver, false);
     }
+
     public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver, boolean forceElGamal) {
         Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
         PublicKey key = config.getRecipientPublicKey();
diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
index 20d69ea733..b4382f97e8 100644
--- a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
+++ b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
@@ -471,7 +471,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
             return;
         }
 
-        int existingTags = GarlicMessageBuilder.estimateAvailableTags(getContext(), _leaseSet.getEncryptionKey());
+        int existingTags = GarlicMessageBuilder.estimateAvailableTags(getContext(), _leaseSet.getEncryptionKey(), _from);
         _outTunnel = selectOutboundTunnel(_to);
         // boolean wantACK = _wantACK || existingTags <= 30 || getContext().random().nextInt(100) < 5;
         // what's the point of 5% random? possible improvements or replacements:
-- 
GitLab