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