diff --git a/core/java/src/net/i2p/crypto/SessionKeyManager.java b/core/java/src/net/i2p/crypto/SessionKeyManager.java index 3a96497e2..441c5312d 100644 --- a/core/java/src/net/i2p/crypto/SessionKeyManager.java +++ b/core/java/src/net/i2p/crypto/SessionKeyManager.java @@ -88,18 +88,18 @@ public class SessionKeyManager { /** * How many to send, IF we need to. - * @since 0.9.1 + * @since 0.9.2 */ public int getTagsToSend() { return 0; }; /** - * @since 0.9.1 + * @since 0.9.2 */ public int getLowThreshold() { return 0; }; /** * @return true if we have less than the threshold or what we have is about to expire - * @since 0.9.1 + * @since 0.9.2 */ public boolean shouldSendTags(PublicKey target, SessionKey key) { return shouldSendTags(target, key, getLowThreshold()); @@ -107,7 +107,7 @@ public class SessionKeyManager { /** * @return true if we have less than the threshold or what we have is about to expire - * @since 0.9.1 + * @since 0.9.2 */ public boolean shouldSendTags(PublicKey target, SessionKey key, int lowThreshold) { return false; } diff --git a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java index fe0d72778..d957d175f 100644 --- a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java +++ b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java @@ -147,7 +147,7 @@ public class TransientSessionKeyManager extends SessionKeyManager { * Use care when adjusting these values. See ConnectionOptions in streaming, * and TransientSessionKeyManager in crypto, for more information. * - * @since 0.9.1 moved from GarlicMessageBuilder to per-SKM config + * @since 0.9.2 moved from GarlicMessageBuilder to per-SKM config */ public static final int DEFAULT_TAGS = 40; /** ditto */ @@ -166,7 +166,7 @@ public class TransientSessionKeyManager extends SessionKeyManager { /** * @param tagsToSend how many to send at a time, may be lower or higher than lowThreshold. 1-128 * @param lowThreshold below this, send more. 1-128 - * @since 0.9.1 + * @since 0.9.2 */ public TransientSessionKeyManager(I2PAppContext context, int tagsToSend, int lowThreshold) { super(context); @@ -354,21 +354,21 @@ public class TransientSessionKeyManager extends SessionKeyManager { /** * How many to send, IF we need to. * @return the configured value (not adjusted for current available) - * @since 0.9.1 + * @since 0.9.2 */ @Override public int getTagsToSend() { return _tagsToSend; }; /** * @return the configured value - * @since 0.9.1 + * @since 0.9.2 */ @Override public int getLowThreshold() { return _lowThreshold; }; /** * @return true if we have less than the threshold or what we have is about to expire - * @since 0.9.1 + * @since 0.9.2 */ @Override public boolean shouldSendTags(PublicKey target, SessionKey key, int lowThreshold) { diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java index 9fba564f8..bb4eb7903 100644 --- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java +++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java @@ -96,7 +96,7 @@ class ClientConnectionRunner { // e.g. on local access private static final int MAX_MESSAGE_ID = 0x4000000; - /** @since 0.9.1 */ + /** @since 0.9.2 */ private static final String PROP_TAGS = "crypto.tagsToSend"; private static final String PROP_THRESH = "crypto.lowTagThreshold"; diff --git a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java index 998e267b5..946a2f32a 100644 --- a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java +++ b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java @@ -55,6 +55,7 @@ public class GarlicMessageBuilder { * * @param ctx scope * @param config how/what to wrap + * @throws IllegalArgumentException on error */ private static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config) { Log log = ctx.logManager().getLog(GarlicMessageBuilder.class); @@ -72,6 +73,7 @@ public class GarlicMessageBuilder { If non-empty on return you must call skm.tagsDelivered() when sent and then call skm.tagsAcked() or skm.failTags() later. * @param skm non-null + * @throws IllegalArgumentException on error */ public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, SessionKeyManager skm) { @@ -99,6 +101,7 @@ public class GarlicMessageBuilder { Set to zero to disable tag delivery. You must set to zero if you are not equipped to confirm delivery and call skm.tagsAcked() or skm.failTags() later. * @param skm non-null + * @throws IllegalArgumentException on error */ public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver, SessionKeyManager skm) { @@ -120,6 +123,7 @@ public class GarlicMessageBuilder { If this is always 0, it forces ElGamal every time. * @param lowTagsThreshold the threshold * @param skm non-null + * @throws IllegalArgumentException on error */ public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver, int lowTagsThreshold, SessionKeyManager skm) { @@ -173,6 +177,7 @@ public class GarlicMessageBuilder { * know the encryptKey and encryptTag) * @param encryptKey sessionKey used to encrypt the current message * @param encryptTag sessionTag used to encrypt the current message + * @throws IllegalArgumentException on error */ public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, PublicKey target, SessionKey encryptKey, SessionTag encryptTag) { @@ -219,8 +224,11 @@ public class GarlicMessageBuilder { ****/ /** - * Build an unencrypted set of cloves specified by the config. + * Build the unencrypted GarlicMessage specified by the config. + * It contains the number of cloves, followed by each clove, + * followed by a certificate, ID, and expiration date. * + * @throws IllegalArgumentException on error */ private static byte[] buildCloveSet(RouterContext ctx, GarlicConfig config) { ByteArrayOutputStream baos = null; @@ -243,8 +251,6 @@ public class GarlicMessageBuilder { // See notes below cloves[i] = buildClove(ctx, c); } - if (cloves[i] == null) - throw new DataFormatException("Unable to build clove"); } int len = 1; @@ -255,15 +261,15 @@ public class GarlicMessageBuilder { for (int i = 0; i < cloves.length; i++) baos.write(cloves[i]); } - if (baos == null) - new ByteArrayOutputStream(16); config.getCertificate().writeBytes(baos); DataHelper.writeLong(baos, 4, config.getId()); DataHelper.writeLong(baos, DataHelper.DATE_LENGTH, config.getExpiration()); } catch (IOException ioe) { log.error("Error building the clove set", ioe); + throw new IllegalArgumentException("Error building the clove set", ioe); } catch (DataFormatException dfe) { log.error("Error building the clove set", dfe); + throw new IllegalArgumentException("Error building the clove set", dfe); } return baos.toByteArray(); } diff --git a/router/java/src/net/i2p/router/message/GarlicMessageReceiver.java b/router/java/src/net/i2p/router/message/GarlicMessageReceiver.java index 0f902c01e..1b0e39ea7 100644 --- a/router/java/src/net/i2p/router/message/GarlicMessageReceiver.java +++ b/router/java/src/net/i2p/router/message/GarlicMessageReceiver.java @@ -36,13 +36,20 @@ public class GarlicMessageReceiver { public void handleClove(DeliveryInstructions instructions, I2NPMessage data); } + /** + * @param receiver non-null + */ public GarlicMessageReceiver(RouterContext context, CloveReceiver receiver) { this(context, receiver, null); } + + /** + * @param receiver non-null + */ public GarlicMessageReceiver(RouterContext context, CloveReceiver receiver, Hash clientDestination) { _context = context; _log = context.logManager().getLog(GarlicMessageReceiver.class); - _context.statManager().createRateStat("crypto.garlic.decryptFail", "How often garlic messages are undecryptable", "Encryption", new long[] { 5*60*1000, 60*60*1000, 24*60*60*1000 }); + _context.statManager().createRateStat("crypto.garlic.decryptFail", "How often garlic messages are undecryptable", "Encryption", new long[] { 60*60*1000, 24*60*60*1000 }); _clientDestination = clientDestination; _parser = new GarlicMessageParser(context); _receiver = receiver; @@ -94,8 +101,7 @@ public class GarlicMessageReceiver { _log.warn("Invalid clove " + clove); return; } - if (_receiver != null) - _receiver.handleClove(clove.getInstructions(), clove.getData()); + _receiver.handleClove(clove.getInstructions(), clove.getData()); } private boolean isValid(GarlicClove clove) { diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageJobHelper.java b/router/java/src/net/i2p/router/message/OutboundClientMessageJobHelper.java index f5a4d3f38..cbbb83434 100644 --- a/router/java/src/net/i2p/router/message/OutboundClientMessageJobHelper.java +++ b/router/java/src/net/i2p/router/message/OutboundClientMessageJobHelper.java @@ -90,6 +90,9 @@ class OutboundClientMessageJobHelper { return msg; } + /** + * @return null on error + */ private static GarlicConfig createGarlicConfig(RouterContext ctx, long replyToken, long expiration, PublicKey recipientPK, PayloadGarlicConfig dataClove, Hash from, Destination dest, TunnelInfo replyTunnel, boolean requireAck, LeaseSet bundledReplyLeaseSet) { @@ -98,8 +101,6 @@ class OutboundClientMessageJobHelper { log.debug("Reply token: " + replyToken); GarlicConfig config = new GarlicConfig(); - config.addClove(dataClove); - if (requireAck) { PayloadGarlicConfig ackClove = buildAckClove(ctx, from, replyTunnel, replyToken, expiration); if (ackClove == null) @@ -112,6 +113,11 @@ class OutboundClientMessageJobHelper { config.addClove(leaseSetClove); } + // As of 0.9.2, since the receiver processes them in-order, + // put data clove last to speed up the ack, + // and get the leaseset stored before handling the data + config.addClove(dataClove); + DeliveryInstructions instructions = new DeliveryInstructions(); instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_LOCAL); // defaults @@ -137,6 +143,7 @@ class OutboundClientMessageJobHelper { /** * Build a clove that sends a DeliveryStatusMessage to us + * @return null on error */ private static PayloadGarlicConfig buildAckClove(RouterContext ctx, Hash from, TunnelInfo replyToTunnel, long replyToken, long expiration) { Log log = ctx.logManager().getLog(OutboundClientMessageJobHelper.class); diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java index d171b6b24..67a490d9f 100644 --- a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java +++ b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java @@ -78,7 +78,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { private final static long OVERALL_TIMEOUT_MS_MIN = 8*1000; /** - * NOTE: Changed as of 0.9.1. + * NOTE: Changed as of 0.9.2. * * Defaults to true. *