NetDB, I2CP: Fix tunnels going yellow for several minutes (Gitlab #487)

This commit is contained in:
zzz
2024-08-16 11:15:15 +00:00
parent 8d4ddd0f17
commit fc728c468e
12 changed files with 155 additions and 36 deletions

View File

@@ -105,6 +105,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
private long _offlineExpiration;
private Signature _offlineSignature;
protected SigningPublicKey _transientSigningPublicKey;
private long _lastLS2SignTime;
// subsession stuff
// registered subsessions
@@ -1185,6 +1186,21 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
SessionId getSessionId() { return _sessionId; }
void setSessionId(SessionId id) { _sessionId = id; }
/**
* The published timestamp of the last LS2 we signed
*
* @return 0 if never
* @since 0.9.64
*/
long getLastLS2SignTime() { return _lastLS2SignTime; };
/**
* The published timestamp of the last LS2 we signed
*
* @since 0.9.64
*/
void setLastLS2SignTime(long now) { _lastLS2SignTime = now; };
/** configure the listener */
public void setSessionListener(I2PSessionListener lsnr) { _sessionListener = lsnr; }

View File

@@ -130,19 +130,25 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
boolean isLS2 = requiresLS2(session);
LeaseSet leaseSet;
if (isLS2) {
LeaseSet2 ls2;
if (_ls2Type == DatabaseEntry.KEY_TYPE_LS2) {
leaseSet = new LeaseSet2();
ls2 = new LeaseSet2();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
leaseSet = new EncryptedLeaseSet();
ls2 = new EncryptedLeaseSet();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_META_LS2) {
leaseSet = new MetaLeaseSet();
ls2= new MetaLeaseSet();
} else {
session.propogateError("Unsupported LS2 type", new Exception());
session.destroySession();
return;
}
if (Boolean.parseBoolean(session.getOptions().getProperty("i2cp.dontPublishLeaseSet")))
((LeaseSet2)leaseSet).setUnpublished();
ls2.setUnpublished();
// ensure 1-second resolution timestamp is higher than last one
long now = Math.max(_context.clock().now(), session.getLastLS2SignTime() + 1000);
ls2.setPublished(now);
session.setLastLS2SignTime(now);
leaseSet = ls2;
} else {
leaseSet = new LeaseSet();
}

View File

@@ -42,19 +42,25 @@ class RequestVariableLeaseSetMessageHandler extends RequestLeaseSetMessageHandle
boolean isLS2 = requiresLS2(session);
LeaseSet leaseSet;
if (isLS2) {
LeaseSet2 ls2;
if (_ls2Type == DatabaseEntry.KEY_TYPE_LS2) {
leaseSet = new LeaseSet2();
ls2 = new LeaseSet2();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
leaseSet = new EncryptedLeaseSet();
ls2 = new EncryptedLeaseSet();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_META_LS2) {
leaseSet = new MetaLeaseSet();
ls2 = new MetaLeaseSet();
} else {
session.propogateError("Unsupported LS2 type", new Exception());
session.destroySession();
return;
}
if (Boolean.parseBoolean(session.getOptions().getProperty("i2cp.dontPublishLeaseSet")))
((LeaseSet2)leaseSet).setUnpublished();
ls2.setUnpublished();
// ensure 1-second resolution timestamp is higher than last one
long now = Math.max(_context.clock().now(), session.getLastLS2SignTime() + 1000);
ls2.setPublished(now);
session.setLastLS2SignTime(now);
leaseSet = ls2;
} else {
leaseSet = new LeaseSet();
}

View File

@@ -310,7 +310,7 @@ public class EncryptedLeaseSet extends LeaseSet2 {
DataHelper.writeLong(out, 2, _signingKey.getType().getCode());
_signingKey.writeBytes(out);
if (_published <= 0)
_published = Clock.getInstance().now();
setPublished(Clock.getInstance().now());
DataHelper.writeLong(out, 4, _published / 1000);
DataHelper.writeLong(out, 2, (_expires - _published) / 1000);
DataHelper.writeLong(out, 2, _flags);

View File

@@ -238,6 +238,9 @@ public class LeaseSet extends DatabaseEntry {
* determine which LeaseSet was published more recently (later earliestLeaseSetDate
* means it was published later)
*
* Warning - do not use this for version comparison for LeaseSet2.
* Use LeaseSet2.getPublished() instead.
*
* @return earliest end date of any lease in the set, or -1 if there are no leases
*/
public long getEarliestLeaseDate() {

View File

@@ -66,6 +66,9 @@ public class LeaseSet2 extends LeaseSet {
* Published timestamp, as received.
* Different than getDate() or getEarliestLeaseDate(), which are the earliest lease expiration.
*
* Use this for LS2 version comparison, NOT getEarliestLeaseDate(), because
* that will return -1 for EncryptedLS and MetaLS.
*
* @return in ms, with 1 second resolution
* @since 0.9.39
*/
@@ -73,6 +76,18 @@ public class LeaseSet2 extends LeaseSet {
return _published;
}
/**
* Set published timestamp.
* Will be rounded to nearest second.
* If not called, will be set on write.
*
* @since 0.9.64
*/
public void setPublished(long now) {
// we round it here, so comparisons during verifies aren't wrong
_published = ((now + 500) / 1000) * 1000;
}
/**
* Published expiration, as received.
* May be different than getLatestLeaseDate(), which is the latest lease expiration.
@@ -524,8 +539,7 @@ public class LeaseSet2 extends LeaseSet {
protected void writeHeader(OutputStream out) throws DataFormatException, IOException {
_destination.writeBytes(out);
if (_published <= 0) {
// we round it here, so comparisons during verifies aren't wrong
_published = ((Clock.getInstance().now() + 500) / 1000) * 1000;
setPublished(Clock.getInstance().now());
}
long pub1k = _published / 1000;
DataHelper.writeLong(out, 4, pub1k);