forked from I2P_Developers/i2p.i2p
Ratchet: Expire outbound TS based on inbound last-used
Fix outbound expiration time Reduce pending tagset expiration Increase max send acks Increase max next key replies Don't save ref to NS callback once called Sync tagset for debug output
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
2020-04-23 zzz
|
||||||
|
* Ratchet: Fixes and parameter adjustments
|
||||||
|
* Streaming: Reduce TCB cache time
|
||||||
|
|
||||||
|
2020-04-21 zzz
|
||||||
|
* Router: Fix logging NPE (thx zlatinb)
|
||||||
|
|
||||||
2020-04-19 zzz
|
2020-04-19 zzz
|
||||||
* Ratchet: Adaptive order of muxed decrypt based on previous traffic
|
* Ratchet: Adaptive order of muxed decrypt based on previous traffic
|
||||||
* Streaming: Single retransmit timer per connection (ticket #2715)
|
* Streaming: Single retransmit timer per connection (ticket #2715)
|
||||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 11;
|
public final static long BUILD = 12;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
@ -68,7 +68,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
*/
|
*/
|
||||||
final static long SESSION_LIFETIME_MAX_MS = SESSION_TAG_DURATION_MS + 3 * 60 * 1000;
|
final static long SESSION_LIFETIME_MAX_MS = SESSION_TAG_DURATION_MS + 3 * 60 * 1000;
|
||||||
|
|
||||||
final static long SESSION_PENDING_DURATION_MS = 5 * 60 * 1000;
|
final static long SESSION_PENDING_DURATION_MS = 3 * 60 * 1000;
|
||||||
// replace an old session created before this if we get a new NS
|
// replace an old session created before this if we get a new NS
|
||||||
private static final long SESSION_REPLACE_AGE = 3*60*1000;
|
private static final long SESSION_REPLACE_AGE = 3*60*1000;
|
||||||
|
|
||||||
@ -518,20 +518,21 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
HandshakeState state = tagSet.getHandshakeState();
|
HandshakeState state = tagSet.getHandshakeState();
|
||||||
if (firstInbound) {
|
if (state == null) {
|
||||||
if (state == null) {
|
// TODO this should really be after decrypt...
|
||||||
// TODO this should really be after decrypt...
|
PublicKey pk = tagSet.getRemoteKey();
|
||||||
PublicKey pk = tagSet.getRemoteKey();
|
if (pk != null) {
|
||||||
if (pk != null) {
|
OutboundSession sess = getSession(pk);
|
||||||
OutboundSession sess = getSession(pk);
|
if (sess != null) {
|
||||||
if (sess != null) {
|
if (firstInbound)
|
||||||
sess.firstTagConsumed(tagSet);
|
sess.firstTagConsumed(tagSet);
|
||||||
} else {
|
else
|
||||||
if (_log.shouldDebug())
|
sess.tagConsumed(tagSet);
|
||||||
_log.debug("First tag consumed but session is gone");
|
} else {
|
||||||
}
|
if (_log.shouldDebug())
|
||||||
} // else null for SingleTagSets
|
_log.debug("Tag consumed but session is gone");
|
||||||
}
|
}
|
||||||
|
} // else null for SingleTagSets
|
||||||
}
|
}
|
||||||
if (_log.shouldDebug()) {
|
if (_log.shouldDebug()) {
|
||||||
if (state != null)
|
if (state != null)
|
||||||
@ -607,12 +608,12 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
// outbound
|
// outbound
|
||||||
int oremoved = 0;
|
int oremoved = 0;
|
||||||
int cremoved = 0;
|
int cremoved = 0;
|
||||||
long exp = now - (SESSION_LIFETIME_MAX_MS / 2);
|
long exp = now - SESSION_TAG_DURATION_MS;
|
||||||
for (Iterator<OutboundSession> iter = _outboundSessions.values().iterator(); iter.hasNext();) {
|
for (Iterator<OutboundSession> iter = _outboundSessions.values().iterator(); iter.hasNext();) {
|
||||||
OutboundSession sess = iter.next();
|
OutboundSession sess = iter.next();
|
||||||
oremoved += sess.expireTags(now);
|
oremoved += sess.expireTags(now);
|
||||||
cremoved += sess.expireCallbacks(now);
|
cremoved += sess.expireCallbacks(now);
|
||||||
if (sess.getLastUsedDate() < exp) {
|
if (sess.getLastUsedDate() < exp || sess.getLastReceivedDate() < exp) {
|
||||||
iter.remove();
|
iter.remove();
|
||||||
oremoved++;
|
oremoved++;
|
||||||
}
|
}
|
||||||
@ -748,26 +749,28 @@ 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.size();
|
synchronized(ts) {
|
||||||
total += size;
|
int size = ts.size();
|
||||||
buf.append("<li><b>ID: ");
|
total += size;
|
||||||
int id = ts.getID();
|
buf.append("<li><b>ID: ");
|
||||||
if (id == RatchetTagSet.DEBUG_IB_NSR)
|
int id = ts.getID();
|
||||||
buf.append("NSR");
|
if (id == RatchetTagSet.DEBUG_IB_NSR)
|
||||||
else if (id == RatchetTagSet.DEBUG_SINGLE_ES)
|
buf.append("NSR");
|
||||||
buf.append("ES");
|
else if (id == RatchetTagSet.DEBUG_SINGLE_ES)
|
||||||
else
|
buf.append("ES");
|
||||||
buf.append(id);
|
else
|
||||||
buf.append('/').append(ts.getDebugID());
|
buf.append(id);
|
||||||
// inbound sets are multi-column, keep it short
|
buf.append('/').append(ts.getDebugID());
|
||||||
//buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
// inbound sets are multi-column, keep it short
|
||||||
// .append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
//buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
||||||
long expires = ts.getExpiration() - now;
|
// .append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
||||||
if (expires > 0)
|
long expires = ts.getExpiration() - now;
|
||||||
buf.append(" expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
if (expires > 0)
|
||||||
else
|
buf.append(" expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
||||||
buf.append(" expired:</b> ").append(DataHelper.formatDuration2(0 - expires)).append(" ago with ");
|
else
|
||||||
buf.append(size).append('+').append(ts.remaining() - size).append(" tags remaining</li>");
|
buf.append(" expired:</b> ").append(DataHelper.formatDuration2(0 - expires)).append(" ago with ");
|
||||||
|
buf.append(size).append('+').append(ts.remaining() - size).append(" tags remaining</li>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf.append("</ul></td></tr>\n");
|
buf.append("</ul></td></tr>\n");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
@ -791,7 +794,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
totalSets += sets.size();
|
totalSets += sets.size();
|
||||||
buf.append("<tr class=\"debug_outboundtarget\"><td><div class=\"debug_targetinfo\"><b>To public key:</b> ").append(toString(sess.getTarget())).append("<br>" +
|
buf.append("<tr class=\"debug_outboundtarget\"><td><div class=\"debug_targetinfo\"><b>To public key:</b> ").append(toString(sess.getTarget())).append("<br>" +
|
||||||
"<b>Established:</b> ").append(DataHelper.formatDuration2(now - sess.getEstablishedDate())).append(" ago<br>" +
|
"<b>Established:</b> ").append(DataHelper.formatDuration2(now - sess.getEstablishedDate())).append(" ago<br>" +
|
||||||
"<b>Last Used:</b> ").append(DataHelper.formatDuration2(now - sess.getLastUsedDate())).append(" ago<br>");
|
"<b>Last Used:</b> ").append(DataHelper.formatDuration2(now - sess.getLastUsedDate())).append(" ago<br>" +
|
||||||
|
"<b>Last Rcvd:</b> ").append(DataHelper.formatDuration2(now - sess.getLastReceivedDate())).append(" ago<br>");
|
||||||
SessionKey sk = sess.getCurrentKey();
|
SessionKey sk = sess.getCurrentKey();
|
||||||
if (sk != null)
|
if (sk != null)
|
||||||
buf.append("<b>Session key:</b> ").append(sk.toBase64());
|
buf.append("<b>Session key:</b> ").append(sk.toBase64());
|
||||||
@ -799,22 +803,29 @@ 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><td colspan=\"2\"><ul>");
|
"<tr><td colspan=\"2\"><ul>");
|
||||||
for (RatchetTagSet ts : sets) {
|
for (RatchetTagSet ts : sets) {
|
||||||
int size = ts.remaining();
|
synchronized(ts) {
|
||||||
buf.append("<li><b>ID: ");
|
int size = ts.remaining();
|
||||||
int id = ts.getID();
|
buf.append("<li><b>ID: ");
|
||||||
if (id == RatchetTagSet.DEBUG_OB_NSR)
|
int id = ts.getID();
|
||||||
buf.append("NSR");
|
if (id == RatchetTagSet.DEBUG_OB_NSR)
|
||||||
else
|
buf.append("NSR");
|
||||||
buf.append(id);
|
else
|
||||||
buf.append('/').append(ts.getDebugID())
|
buf.append(id);
|
||||||
.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
buf.append('/').append(ts.getDebugID());
|
||||||
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
if (ts.getAcked())
|
||||||
long expires = ts.getExpiration() - now;
|
buf.append(" acked");
|
||||||
if (expires > 0)
|
buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
||||||
buf.append(" <b>expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
||||||
else
|
long expires = ts.getExpiration() - now;
|
||||||
buf.append(" <b>expired:</b> ").append(DataHelper.formatDuration2(0 - expires)).append(" ago with ");
|
if (expires > 0)
|
||||||
buf.append(size).append(" tags remaining; acked? ").append(ts.getAcked()).append("</li>");
|
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");
|
||||||
|
if (ts.getNextKey() != null)
|
||||||
|
buf.append(" <b>NK sent</b>");
|
||||||
|
}
|
||||||
|
buf.append("</li>");
|
||||||
}
|
}
|
||||||
buf.append("</ul></td></tr>\n");
|
buf.append("</ul></td></tr>\n");
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
@ -852,11 +863,12 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
private class OutboundSession {
|
private class OutboundSession {
|
||||||
private final PublicKey _target;
|
private final PublicKey _target;
|
||||||
private final HandshakeState _state;
|
private final HandshakeState _state;
|
||||||
private final ReplyCallback _NScallback;
|
private ReplyCallback _NScallback;
|
||||||
private ReplyCallback _NSRcallback;
|
private ReplyCallback _NSRcallback;
|
||||||
private SessionKey _currentKey;
|
private SessionKey _currentKey;
|
||||||
private final long _established;
|
private final long _established;
|
||||||
private long _lastUsed;
|
private long _lastUsed;
|
||||||
|
private long _lastReceived;
|
||||||
/**
|
/**
|
||||||
* Before the first ack, all tagsets go here. These are never expired, we rely
|
* Before the first ack, all tagsets go here. These are never expired, we rely
|
||||||
* on the callers to call failTags() or ackTags() to remove them from this list.
|
* on the callers to call failTags() or ackTags() to remove them from this list.
|
||||||
@ -898,9 +910,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
private SessionKey _nextIBRootKey;
|
private SessionKey _nextIBRootKey;
|
||||||
|
|
||||||
private static final String INFO_7 = "XDHRatchetTagSet";
|
private static final String INFO_7 = "XDHRatchetTagSet";
|
||||||
private static final int MAX_FAILS = 2;
|
private static final int MAX_SEND_ACKS = 16;
|
||||||
private static final int MAX_SEND_ACKS = 8;
|
private static final int MAX_SEND_REVERSE_KEY = 64;
|
||||||
private static final int MAX_SEND_REVERSE_KEY = 25;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param key may be null
|
* @param key may be null
|
||||||
@ -912,6 +923,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
_NScallback = callback;
|
_NScallback = callback;
|
||||||
_established = _context.clock().now();
|
_established = _context.clock().now();
|
||||||
_lastUsed = _established;
|
_lastUsed = _established;
|
||||||
|
_lastReceived = _established;
|
||||||
_unackedTagSets = new HashSet<RatchetTagSet>(4);
|
_unackedTagSets = new HashSet<RatchetTagSet>(4);
|
||||||
_callbacks = new ConcurrentHashMap<Integer, ReplyCallback>();
|
_callbacks = new ConcurrentHashMap<Integer, ReplyCallback>();
|
||||||
_acksToSend = new LinkedBlockingQueue<Integer>();
|
_acksToSend = new LinkedBlockingQueue<Integer>();
|
||||||
@ -962,6 +974,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
SessionKey rk = new SessionKey(ck);
|
SessionKey rk = new SessionKey(ck);
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
_lastUsed = now;
|
_lastUsed = now;
|
||||||
|
_lastReceived = now;
|
||||||
boolean isInbound = state.getRole() == HandshakeState.RESPONDER;
|
boolean isInbound = state.getRole() == HandshakeState.RESPONDER;
|
||||||
if (isInbound) {
|
if (isInbound) {
|
||||||
// We are Bob
|
// We are Bob
|
||||||
@ -996,12 +1009,14 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
synchronized (_unackedTagSets) {
|
synchronized (_unackedTagSets) {
|
||||||
_tagSet = tagset_ab;
|
_tagSet = tagset_ab;
|
||||||
_unackedTagSets.clear();
|
_unackedTagSets.clear();
|
||||||
|
// Bob received the NS, call the callback
|
||||||
|
if (_NScallback != null) {
|
||||||
|
_NScallback.onReply();
|
||||||
|
_NScallback = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// We can't destroy the original state, as more NSRs may come in
|
// We can't destroy the original state, as more NSRs may come in
|
||||||
//_state.destroy();
|
//_state.destroy();
|
||||||
// Bob received the NS, call the callback
|
|
||||||
if (_NScallback != null)
|
|
||||||
_NScallback.onReply();
|
|
||||||
}
|
}
|
||||||
// kills the keys for future NSRs
|
// kills the keys for future NSRs
|
||||||
//state.destroy();
|
//state.destroy();
|
||||||
@ -1225,6 +1240,16 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tag was received for this inbound (ES) tagset.
|
||||||
|
*
|
||||||
|
* @param set the inbound tagset
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
void tagConsumed(RatchetTagSet set) {
|
||||||
|
_lastReceived = set.getDate();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First tag was received for this inbound (ES) tagset.
|
* First tag was received for this inbound (ES) tagset.
|
||||||
* Find the corresponding outbound (ES) tagset in _unackedTagSets,
|
* Find the corresponding outbound (ES) tagset in _unackedTagSets,
|
||||||
@ -1233,6 +1258,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
* @param set the inbound tagset
|
* @param set the inbound tagset
|
||||||
*/
|
*/
|
||||||
void firstTagConsumed(RatchetTagSet set) {
|
void firstTagConsumed(RatchetTagSet set) {
|
||||||
|
tagConsumed(set);
|
||||||
SessionKey sk = set.getAssociatedKey();
|
SessionKey sk = set.getAssociatedKey();
|
||||||
synchronized (_unackedTagSets) {
|
synchronized (_unackedTagSets) {
|
||||||
// save next root key
|
// save next root key
|
||||||
@ -1300,6 +1326,14 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
return _lastUsed;
|
return _lastUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ONLY updated for inbound NS/NSR/ES tag used
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public long getLastReceivedDate() {
|
||||||
|
return _lastReceived;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expire old tags, returning the number of tag sets removed
|
* Expire old tags, returning the number of tag sets removed
|
||||||
*/
|
*/
|
||||||
@ -1325,6 +1359,11 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
|
|
||||||
public RatchetEntry consumeNext() {
|
public RatchetEntry consumeNext() {
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
|
if (_lastReceived + SESSION_TAG_DURATION_MS < now) {
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_log.info("Expired OB session because IB TS expired");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
synchronized (_unackedTagSets) {
|
synchronized (_unackedTagSets) {
|
||||||
if (_tagSet != null) {
|
if (_tagSet != null) {
|
||||||
synchronized(_tagSet) {
|
synchronized(_tagSet) {
|
||||||
|
Reference in New Issue
Block a user