forked from I2P_Developers/i2p.i2p
Ratchet: Implement expiration
Store creation and last-used in tagset Catch all decrypt/encrypt exceptions Debug page improvements
This commit is contained in:
@ -125,7 +125,20 @@ public final class ECIESAEADEngine {
|
|||||||
*
|
*
|
||||||
* @return decrypted data or null on failure
|
* @return decrypted data or null on failure
|
||||||
*/
|
*/
|
||||||
public CloveSet decrypt(byte data[], PrivateKey targetPrivateKey, RatchetSKM keyManager) throws DataFormatException {
|
public CloveSet decrypt(byte data[], PrivateKey targetPrivateKey,
|
||||||
|
RatchetSKM keyManager) throws DataFormatException {
|
||||||
|
try {
|
||||||
|
return x_decrypt(data, targetPrivateKey, keyManager);
|
||||||
|
} catch (DataFormatException dfe) {
|
||||||
|
throw dfe;
|
||||||
|
} catch (Exception e) {
|
||||||
|
_log.error("ECIES decrypt error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CloveSet x_decrypt(byte data[], PrivateKey targetPrivateKey,
|
||||||
|
RatchetSKM keyManager) throws DataFormatException {
|
||||||
if (targetPrivateKey.getType() != EncType.ECIES_X25519)
|
if (targetPrivateKey.getType() != EncType.ECIES_X25519)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
@ -514,6 +527,16 @@ public final class ECIESAEADEngine {
|
|||||||
*/
|
*/
|
||||||
public byte[] encrypt(CloveSet cloves, PublicKey target, PrivateKey priv,
|
public byte[] encrypt(CloveSet cloves, PublicKey target, PrivateKey priv,
|
||||||
RatchetSKM keyManager) {
|
RatchetSKM keyManager) {
|
||||||
|
try {
|
||||||
|
return x_encrypt(cloves, target, priv, keyManager);
|
||||||
|
} catch (Exception e) {
|
||||||
|
_log.error("ECIES encrypt error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] x_encrypt(CloveSet cloves, PublicKey target, PrivateKey priv,
|
||||||
|
RatchetSKM keyManager) {
|
||||||
if (target.getType() != EncType.ECIES_X25519)
|
if (target.getType() != EncType.ECIES_X25519)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (Arrays.equals(target.getData(), NULLPK)) {
|
if (Arrays.equals(target.getData(), NULLPK)) {
|
||||||
|
@ -31,7 +31,7 @@ import net.i2p.data.SessionKey;
|
|||||||
import net.i2p.data.SessionTag;
|
import net.i2p.data.SessionTag;
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.SimpleTimer;
|
import net.i2p.util.SimpleTimer2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -97,7 +97,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
// start the precalc of Elg2 keys if it wasn't already started
|
// start the precalc of Elg2 keys if it wasn't already started
|
||||||
context.eciesEngine().startup();
|
context.eciesEngine().startup();
|
||||||
_alive = true;
|
_alive = true;
|
||||||
_context.simpleTimer2().addEvent(new CleanupEvent(), 60*1000);
|
new CleanupEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -107,12 +107,17 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
_outboundSessions.clear();
|
_outboundSessions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CleanupEvent implements SimpleTimer.TimedEvent {
|
private class CleanupEvent extends SimpleTimer2.TimedEvent {
|
||||||
|
public CleanupEvent() {
|
||||||
|
// wait until outbound expiration time to start
|
||||||
|
super(_context.simpleTimer2(), SESSION_TAG_DURATION_MS);
|
||||||
|
}
|
||||||
|
|
||||||
public void timeReached() {
|
public void timeReached() {
|
||||||
if (!_alive)
|
if (!_alive)
|
||||||
return;
|
return;
|
||||||
// TODO
|
aggressiveExpire();
|
||||||
_context.simpleTimer2().addEvent(this, 60*1000);
|
schedule(60*1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,6 +525,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
HandshakeState state = tagSet.getHandshakeState();
|
HandshakeState state = tagSet.getHandshakeState();
|
||||||
synchronized(tagSet) {
|
synchronized(tagSet) {
|
||||||
key = tagSet.consume(tag);
|
key = tagSet.consume(tag);
|
||||||
|
if (key != null)
|
||||||
|
tagSet.setDate(_context.clock().now());
|
||||||
}
|
}
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
@ -563,7 +570,35 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
* @return number of tag sets expired (bogus as it overcounts inbound)
|
* @return number of tag sets expired (bogus as it overcounts inbound)
|
||||||
*/
|
*/
|
||||||
private int aggressiveExpire() {
|
private int aggressiveExpire() {
|
||||||
return 0;
|
long now = _context.clock().now();
|
||||||
|
long exp = now - SESSION_LIFETIME_MAX_MS;
|
||||||
|
|
||||||
|
// inbound
|
||||||
|
int removed = 0;
|
||||||
|
for (Iterator<RatchetTagSet> iter = _inboundTagSets.values().iterator(); iter.hasNext();) {
|
||||||
|
RatchetTagSet ts = iter.next();
|
||||||
|
if (ts.getDate() < exp) {
|
||||||
|
iter.remove();
|
||||||
|
removed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removed > 0 && _log.shouldInfo())
|
||||||
|
_log.info("Expired inbound: " + removed);
|
||||||
|
|
||||||
|
// outbound
|
||||||
|
int oremoved = 0;
|
||||||
|
exp = now - (SESSION_LIFETIME_MAX_MS / 2);
|
||||||
|
for (Iterator<OutboundSession> iter = _outboundSessions.values().iterator(); iter.hasNext();) {
|
||||||
|
OutboundSession sess = iter.next();
|
||||||
|
oremoved += sess.expireTags();
|
||||||
|
if (sess.getLastUsedDate() < exp) {
|
||||||
|
iter.remove();
|
||||||
|
oremoved++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oremoved > 0 && _log.shouldInfo())
|
||||||
|
_log.info("Expired outbound: " + oremoved);
|
||||||
|
return removed + oremoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// begin SessionTagListener ///
|
/// begin SessionTagListener ///
|
||||||
@ -607,12 +642,15 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
@Override
|
@Override
|
||||||
public void renderStatusHTML(Writer out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
StringBuilder buf = new StringBuilder(1024);
|
StringBuilder buf = new StringBuilder(1024);
|
||||||
|
|
||||||
|
// inbound
|
||||||
buf.append("<h3 class=\"debug_inboundsessions\">Ratchet Inbound sessions</h3>" +
|
buf.append("<h3 class=\"debug_inboundsessions\">Ratchet Inbound sessions</h3>" +
|
||||||
"<table>");
|
"<table>");
|
||||||
Map<SessionKey, Set<RatchetTagSet>> inboundSets = getRatchetTagSetsBySessionKey();
|
Map<SessionKey, Set<RatchetTagSet>> inboundSets = getRatchetTagSetsBySessionKey();
|
||||||
int total = 0;
|
int total = 0;
|
||||||
int totalSets = 0;
|
int totalSets = 0;
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
|
long exp = now + SESSION_LIFETIME_MAX_MS;
|
||||||
Set<RatchetTagSet> sets = new TreeSet<RatchetTagSet>(new RatchetTagSetComparator());
|
Set<RatchetTagSet> sets = new TreeSet<RatchetTagSet>(new RatchetTagSetComparator());
|
||||||
for (Map.Entry<SessionKey, Set<RatchetTagSet>> e : inboundSets.entrySet()) {
|
for (Map.Entry<SessionKey, Set<RatchetTagSet>> e : inboundSets.entrySet()) {
|
||||||
SessionKey skey = e.getKey();
|
SessionKey skey = e.getKey();
|
||||||
@ -623,15 +661,16 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
"<td><b>Sets:</b> ").append(sets.size()).append("</td></tr>" +
|
"<td><b>Sets:</b> ").append(sets.size()).append("</td></tr>" +
|
||||||
"<tr class=\"expiry\"><td colspan=\"2\"><ul>");
|
"<tr class=\"expiry\"><td colspan=\"2\"><ul>");
|
||||||
for (RatchetTagSet ts : sets) {
|
for (RatchetTagSet ts : sets) {
|
||||||
int size = ts.getTags().size();
|
int size = ts.size();
|
||||||
total += size;
|
total += size;
|
||||||
buf.append("<li><b>ID: ").append(ts.getID());
|
buf.append("<li><b>ID: ").append(ts.getID());
|
||||||
long expires = ts.getDate() - now;
|
buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()));
|
||||||
|
long expires = exp - ts.getDate();
|
||||||
if (expires > 0)
|
if (expires > 0)
|
||||||
buf.append(" expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
buf.append(" <b>expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
||||||
else
|
else
|
||||||
buf.append(" expired:</b> ").append(DataHelper.formatDuration2(0 - expires)).append(" ago with ");
|
buf.append(" <b>expired:</b> ").append(DataHelper.formatDuration2(0 - expires)).append(" ago with ");
|
||||||
buf.append(size).append('/').append(ts.getOriginalSize()).append(" tags remaining</li>");
|
buf.append(size).append('/').append(ts.remaining()).append(" tags remaining</li>");
|
||||||
}
|
}
|
||||||
buf.append("</ul></td></tr>\n");
|
buf.append("</ul></td></tr>\n");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
@ -644,11 +683,12 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
"</table>" +
|
"</table>" +
|
||||||
"<h3 class=\"debug_outboundsessions\">Ratchet Outbound sessions</h3>" +
|
"<h3 class=\"debug_outboundsessions\">Ratchet Outbound sessions</h3>" +
|
||||||
"<table>");
|
"<table>");
|
||||||
total = 0;
|
|
||||||
|
// outbound
|
||||||
totalSets = 0;
|
totalSets = 0;
|
||||||
|
exp = now + SESSION_TAG_DURATION_MS;
|
||||||
Set<OutboundSession> outbound = getOutboundSessions();
|
Set<OutboundSession> outbound = getOutboundSessions();
|
||||||
for (Iterator<OutboundSession> iter = outbound.iterator(); iter.hasNext();) {
|
for (OutboundSession sess : outbound) {
|
||||||
OutboundSession sess = iter.next();
|
|
||||||
sets.clear();
|
sets.clear();
|
||||||
sets.addAll(sess.getTagSets());
|
sets.addAll(sess.getTagSets());
|
||||||
totalSets += sets.size();
|
totalSets += sets.size();
|
||||||
@ -662,20 +702,22 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
buf.append("</div></td>" +
|
buf.append("</div></td>" +
|
||||||
"<td><b># Sets:</b> ").append(sess.getTagSets().size()).append("</td></tr>" +
|
"<td><b># Sets:</b> ").append(sess.getTagSets().size()).append("</td></tr>" +
|
||||||
"<tr><td colspan=\"2\"><ul>");
|
"<tr><td colspan=\"2\"><ul>");
|
||||||
for (Iterator<RatchetTagSet> siter = sets.iterator(); siter.hasNext();) {
|
for (RatchetTagSet ts : sets) {
|
||||||
RatchetTagSet ts = siter.next();
|
int size = ts.remaining();
|
||||||
int size = ts.getTags().size();
|
|
||||||
total += size;
|
|
||||||
buf.append("<li><b>ID: ").append(ts.getID())
|
buf.append("<li><b>ID: ").append(ts.getID())
|
||||||
.append(" Sent:</b> ").append(DataHelper.formatDuration2(now - ts.getDate())).append(" ago with ");
|
.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()));
|
||||||
buf.append(size).append('/').append(ts.getOriginalSize()).append(" tags remaining; acked? ").append(ts.getAcked()).append("</li>");
|
long expires = exp - ts.getDate();
|
||||||
|
if (expires > 0)
|
||||||
|
buf.append(" <b>expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
||||||
|
else
|
||||||
|
buf.append(" <b>expired:</b> ").append(DataHelper.formatDuration2(0 - expires)).append(" ago with ");
|
||||||
|
buf.append(size).append(" tags remaining; acked? ").append(ts.getAcked()).append("</li>");
|
||||||
}
|
}
|
||||||
buf.append("</ul></td></tr>\n");
|
buf.append("</ul></td></tr>\n");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
buf.append("<tr><th colspan=\"2\">Total outbound tags: ").append(total).append(" (")
|
buf.append("<tr><th colspan=\"2\">Total sets: ").append(totalSets)
|
||||||
.append(DataHelper.formatSize2(32*total)).append("B); sets: ").append(totalSets)
|
|
||||||
.append("; sessions: ").append(outbound.size())
|
.append("; sessions: ").append(outbound.size())
|
||||||
.append("</th></tr>\n</table>");
|
.append("</th></tr>\n</table>");
|
||||||
|
|
||||||
@ -697,10 +739,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
*/
|
*/
|
||||||
private static class RatchetTagSetComparator implements Comparator<RatchetTagSet>, Serializable {
|
private static class RatchetTagSetComparator implements Comparator<RatchetTagSet>, Serializable {
|
||||||
public int compare(RatchetTagSet l, RatchetTagSet r) {
|
public int compare(RatchetTagSet l, RatchetTagSet r) {
|
||||||
int rv = (int) (l.getDate() - r.getDate());
|
return l.getID() - r.getID();
|
||||||
if (rv != 0)
|
|
||||||
return rv;
|
|
||||||
return l.hashCode() - r.hashCode();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -884,7 +923,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
if (_log.shouldWarn()) {
|
if (_log.shouldWarn()) {
|
||||||
int dropped = 0;
|
int dropped = 0;
|
||||||
for (RatchetTagSet set : _tagSets) {
|
for (RatchetTagSet set : _tagSets) {
|
||||||
dropped += set.getTags().size();
|
dropped += set.remaining();
|
||||||
}
|
}
|
||||||
_log.warn("Rekeyed from " + _currentKey + " to " + key
|
_log.warn("Rekeyed from " + _currentKey + " to " + key
|
||||||
+ ": dropping " + dropped + " session tags", new Exception());
|
+ ": dropping " + dropped + " session tags", new Exception());
|
||||||
@ -944,6 +983,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
|
if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
|
||||||
RatchetSessionTag tag = set.consumeNext();
|
RatchetSessionTag tag = set.consumeNext();
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
|
set.setDate(now);
|
||||||
SessionKeyAndNonce skn = set.consumeNextKey();
|
SessionKeyAndNonce skn = set.consumeNextKey();
|
||||||
return new RatchetEntry(tag, skn);
|
return new RatchetEntry(tag, skn);
|
||||||
} else if (_log.shouldInfo()) {
|
} else if (_log.shouldInfo()) {
|
||||||
@ -970,8 +1010,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
if (!set.getAcked())
|
if (!set.getAcked())
|
||||||
continue;
|
continue;
|
||||||
if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
|
if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
|
||||||
/////////// just add fixed number?
|
// or just add fixed number?
|
||||||
int sz = set.getTags().size();
|
int sz = set.remaining();
|
||||||
tags += sz;
|
tags += sz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -988,7 +1028,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
long last = 0;
|
long last = 0;
|
||||||
synchronized (_tagSets) {
|
synchronized (_tagSets) {
|
||||||
for (RatchetTagSet set : _tagSets) {
|
for (RatchetTagSet set : _tagSets) {
|
||||||
if ( (set.getDate() > last) && (!set.getTags().isEmpty()) )
|
if (set.getDate() > last && set.remaining() > 0)
|
||||||
last = set.getDate();
|
last = set.getDate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package net.i2p.router.crypto.ratchet;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -14,6 +13,7 @@ import net.i2p.I2PAppContext;
|
|||||||
import net.i2p.crypto.HKDF;
|
import net.i2p.crypto.HKDF;
|
||||||
import net.i2p.crypto.TagSetHandle;
|
import net.i2p.crypto.TagSetHandle;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.SessionKey;
|
import net.i2p.data.SessionKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +38,8 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
// We use byte[] for key to save space, because we don't need indexOfValueByValue()
|
// We use byte[] for key to save space, because we don't need indexOfValueByValue()
|
||||||
private final SparseArray<byte[]> _sessionKeys;
|
private final SparseArray<byte[]> _sessionKeys;
|
||||||
private final HKDF hkdf;
|
private final HKDF hkdf;
|
||||||
private final long _date;
|
private final long _created;
|
||||||
|
private long _date;
|
||||||
private final int _id;
|
private final int _id;
|
||||||
private final int _originalSize;
|
private final int _originalSize;
|
||||||
private final int _maxSize;
|
private final int _maxSize;
|
||||||
@ -57,7 +58,8 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
private static final String INFO_4 = "SessionTagKeyGen";
|
private static final String INFO_4 = "SessionTagKeyGen";
|
||||||
private static final String INFO_5 = "SymmetricRatchet";
|
private static final String INFO_5 = "SymmetricRatchet";
|
||||||
private static final byte[] ZEROLEN = new byte[0];
|
private static final byte[] ZEROLEN = new byte[0];
|
||||||
private static final int TAGLEN = 8;
|
private static final int TAGLEN = RatchetSessionTag.LENGTH;
|
||||||
|
private static final int MAX = 65535;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Outbound NSR Tagset
|
* Outbound NSR Tagset
|
||||||
@ -82,7 +84,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
/**
|
/**
|
||||||
* Inbound NSR Tagset
|
* Inbound NSR Tagset
|
||||||
*
|
*
|
||||||
* @param date For inbound: when the TagSet will expire
|
* @param date For inbound: creation time
|
||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, int minSize, int maxSize) {
|
long date, int id, int minSize, int maxSize) {
|
||||||
@ -92,7 +94,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
/**
|
/**
|
||||||
* Inbound ES Tagset
|
* Inbound ES Tagset
|
||||||
*
|
*
|
||||||
* @param date For inbound: when the TagSet will expire
|
* @param date For inbound: creation time
|
||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, int minSize, int maxSize) {
|
long date, int id, int minSize, int maxSize) {
|
||||||
@ -101,13 +103,14 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param date For inbound: when the TagSet will expire; for outbound: creation time
|
* @param date For inbound and outbound: creation time
|
||||||
*/
|
*/
|
||||||
private RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
private RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, boolean isInbound, int minSize, int maxSize) {
|
long date, int id, boolean isInbound, int minSize, int maxSize) {
|
||||||
_lsnr = lsnr;
|
_lsnr = lsnr;
|
||||||
_state = state;
|
_state = state;
|
||||||
_key = rootKey;
|
_key = rootKey;
|
||||||
|
_created = date;
|
||||||
_date = date;
|
_date = date;
|
||||||
_id = id;
|
_id = id;
|
||||||
_originalSize = minSize;
|
_originalSize = minSize;
|
||||||
@ -161,27 +164,64 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For inbound: when the TagSet will expire; for outbound: creation time
|
* For inbound and outbound: last used time
|
||||||
*/
|
*/
|
||||||
public long getDate() {
|
public long getDate() {
|
||||||
return _date;
|
return _date;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** for debugging */
|
/**
|
||||||
public int getOriginalSize() {
|
* For inbound and outbound: last used time
|
||||||
return 0;
|
*/
|
||||||
|
public void setDate(long when) {
|
||||||
|
_date = when;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For inbound and outbound: creation time
|
||||||
|
*/
|
||||||
|
public long getCreated() {
|
||||||
|
return _created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** for debugging */
|
||||||
|
public int getOriginalSize() {
|
||||||
|
return _originalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unused tags generated
|
||||||
|
* @return 0 for outbound
|
||||||
|
*/
|
||||||
public int size() {
|
public int size() {
|
||||||
return _sessionTags != null ? _sessionTags.size() : 0;
|
return _sessionTags != null ? _sessionTags.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tags remaining
|
||||||
|
* @return 0 - 65535
|
||||||
|
*/
|
||||||
|
public int remaining() {
|
||||||
|
int nextKey;
|
||||||
|
if (_sessionTags != null) {
|
||||||
|
// IB
|
||||||
|
if (_sessionTags.size() <= 0)
|
||||||
|
nextKey = 0;
|
||||||
|
else
|
||||||
|
nextKey = _sessionTags.keyAt(0);
|
||||||
|
} else {
|
||||||
|
// OB
|
||||||
|
nextKey = _lastTag + 1;
|
||||||
|
}
|
||||||
|
return MAX - nextKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tags still available
|
* tags still available
|
||||||
* inbound only
|
* inbound only
|
||||||
* testing only
|
* testing only
|
||||||
*/
|
*/
|
||||||
public List<RatchetSessionTag> getTags() {
|
private List<RatchetSessionTag> getTags() {
|
||||||
if (_sessionTags == null)
|
if (_sessionTags == null)
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
int sz = _sessionTags.size();
|
int sz = _sessionTags.size();
|
||||||
@ -197,7 +237,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
* inbound only
|
* inbound only
|
||||||
* testing only
|
* testing only
|
||||||
*/
|
*/
|
||||||
public RatchetSessionTag getFirstTag() {
|
private RatchetSessionTag getFirstTag() {
|
||||||
if (_sessionTags == null)
|
if (_sessionTags == null)
|
||||||
throw new IllegalStateException("Outbound tagset");
|
throw new IllegalStateException("Outbound tagset");
|
||||||
if (_sessionTags.size() <= 0)
|
if (_sessionTags.size() <= 0)
|
||||||
@ -343,10 +383,14 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
buf.append("NSR ");
|
buf.append("NSR ");
|
||||||
else
|
else
|
||||||
buf.append("ES ");
|
buf.append("ES ");
|
||||||
buf.append("TagSet #").append(_id).append(" created: ").append(new Date(_date));
|
buf.append("TagSet #").append(_id)
|
||||||
|
.append(" created: ").append(DataHelper.formatTime(_created))
|
||||||
|
.append(" last use: ").append(DataHelper.formatTime(_date));
|
||||||
int sz = size();
|
int sz = size();
|
||||||
buf.append(" Size: ").append(sz);
|
buf.append(" Size: ").append(sz)
|
||||||
buf.append('/').append(getOriginalSize());
|
.append(" Orig: ").append(_originalSize)
|
||||||
|
.append(" Max: ").append(_maxSize)
|
||||||
|
.append(" Remaining: ").append(remaining());
|
||||||
buf.append(" Acked? ").append(_acked);
|
buf.append(" Acked? ").append(_acked);
|
||||||
if (_sessionTags != null) {
|
if (_sessionTags != null) {
|
||||||
buf.append(" Inbound");
|
buf.append(" Inbound");
|
||||||
|
Reference in New Issue
Block a user