forked from I2P_Developers/i2p.i2p
NetDB: Track client that requested LS
OCMOSJ: Don't send to a RAP LS
This commit is contained in:
@ -70,6 +70,7 @@ public class LeaseSet extends DatabaseEntry {
|
|||||||
protected final List<Lease> _leases;
|
protected final List<Lease> _leases;
|
||||||
protected boolean _receivedAsPublished;
|
protected boolean _receivedAsPublished;
|
||||||
private boolean _receivedAsReply;
|
private boolean _receivedAsReply;
|
||||||
|
private Hash _receivedBy;
|
||||||
// Store these since isCurrent() and getEarliestLeaseDate() are called frequently
|
// Store these since isCurrent() and getEarliestLeaseDate() are called frequently
|
||||||
private long _firstExpiration;
|
private long _firstExpiration;
|
||||||
protected long _lastExpiration;
|
protected long _lastExpiration;
|
||||||
@ -198,9 +199,30 @@ public class LeaseSet extends DatabaseEntry {
|
|||||||
*/
|
*/
|
||||||
public boolean getReceivedAsReply() { return _receivedAsReply; }
|
public boolean getReceivedAsReply() { return _receivedAsReply; }
|
||||||
|
|
||||||
/** set to true @since 0.7.14 */
|
/**
|
||||||
|
* set to true
|
||||||
|
* @since 0.7.14
|
||||||
|
*/
|
||||||
public void setReceivedAsReply() { _receivedAsReply = true; }
|
public void setReceivedAsReply() { _receivedAsReply = true; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Hash of the local client that received this LS,
|
||||||
|
* null if the router or unknown.
|
||||||
|
*
|
||||||
|
* @since 0.9.47
|
||||||
|
*/
|
||||||
|
public Hash getReceivedBy() { return _receivedBy; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Also sets receivedAsReply to true
|
||||||
|
* @param localClient may be null
|
||||||
|
* @since 0.9.47
|
||||||
|
*/
|
||||||
|
public void setReceivedBy(Hash localClient) {
|
||||||
|
_receivedAsReply = true;
|
||||||
|
_receivedBy = localClient;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws IllegalStateException if already signed
|
* @throws IllegalStateException if already signed
|
||||||
*/
|
*/
|
||||||
|
@ -74,6 +74,17 @@ public abstract class NetworkDatabaseFacade implements Service {
|
|||||||
*/
|
*/
|
||||||
public abstract void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest);
|
public abstract void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unconditionally lookup using the client's tunnels.
|
||||||
|
*
|
||||||
|
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory
|
||||||
|
* @param onFindJob may be null
|
||||||
|
* @param onFailedLookupJob may be null
|
||||||
|
* @since 0.9.47
|
||||||
|
*/
|
||||||
|
public abstract void lookupLeaseSetRemotely(Hash key, Job onFindJob, Job onFailedLookupJob,
|
||||||
|
long timeoutMs, Hash fromLocalDest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup using the client's tunnels
|
* Lookup using the client's tunnels
|
||||||
* Succeeds even if LS validation fails due to unsupported sig type
|
* Succeeds even if LS validation fails due to unsupported sig type
|
||||||
|
@ -45,6 +45,8 @@ public class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
|||||||
public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, Hash fromLocalDest) {}
|
public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, Hash fromLocalDest) {}
|
||||||
public LeaseSet lookupLeaseSetLocally(Hash key) { return null; }
|
public LeaseSet lookupLeaseSetLocally(Hash key) { return null; }
|
||||||
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {}
|
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {}
|
||||||
|
public void lookupLeaseSetRemotely(Hash key, Job onFindJob, Job onFailedLookupJob,
|
||||||
|
long timeoutMs, Hash fromLocalDest) {}
|
||||||
|
|
||||||
public void lookupDestination(Hash key, Job onFinishedJob, long timeoutMs, Hash fromLocalDest) {}
|
public void lookupDestination(Hash key, Job onFinishedJob, long timeoutMs, Hash fromLocalDest) {}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
|||||||
_to = msg.getDestination();
|
_to = msg.getDestination();
|
||||||
Hash toHash = _to.calculateHash();
|
Hash toHash = _to.calculateHash();
|
||||||
_hashPair = new OutboundCache.HashPair(_from.calculateHash(), toHash);
|
_hashPair = new OutboundCache.HashPair(_from.calculateHash(), toHash);
|
||||||
_toString = toHash.toBase64().substring(0,4);
|
_toString = toHash.toBase32();
|
||||||
// we look up here rather than runJob() so we may adjust the timeout
|
// we look up here rather than runJob() so we may adjust the timeout
|
||||||
_leaseSet = ctx.netDb().lookupLeaseSetLocally(toHash);
|
_leaseSet = ctx.netDb().lookupLeaseSetLocally(toHash);
|
||||||
|
|
||||||
@ -297,6 +297,23 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
|||||||
SendJob success = new SendJob(getContext());
|
SendJob success = new SendJob(getContext());
|
||||||
// set in constructor
|
// set in constructor
|
||||||
if (_leaseSet != null) {
|
if (_leaseSet != null) {
|
||||||
|
if (!_leaseSet.getReceivedAsReply()) {
|
||||||
|
boolean shouldFetch = true;
|
||||||
|
if (_leaseSet.getType() != DatabaseEntry.KEY_TYPE_LEASESET) {
|
||||||
|
LeaseSet2 ls2 = (LeaseSet2) _leaseSet;
|
||||||
|
shouldFetch = !ls2.isUnpublished() || ls2.isBlindedWhenPublished();
|
||||||
|
}
|
||||||
|
if (shouldFetch) {
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_log.info(getJobId() + ": RAP LS, firing search: " + _leaseSet.getHash().toBase32());
|
||||||
|
LookupLeaseSetFailedJob failed = new LookupLeaseSetFailedJob(getContext());
|
||||||
|
getContext().netDb().lookupLeaseSetRemotely(_leaseSet.getHash(), success, failed,
|
||||||
|
LS_LOOKUP_TIMEOUT, _from.calculateHash());
|
||||||
|
} else {
|
||||||
|
dieFatal(MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug(getJobId() + ": Send outbound client message - leaseSet found locally for " + _toString);
|
_log.debug(getJobId() + ": Send outbound client message - leaseSet found locally for " + _toString);
|
||||||
if (!_leaseSet.isCurrent(Router.CLOCK_FUDGE_FACTOR / 4)) {
|
if (!_leaseSet.isCurrent(Router.CLOCK_FUDGE_FACTOR / 4)) {
|
||||||
@ -405,13 +422,17 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
|||||||
*/
|
*/
|
||||||
private int getNextLease() {
|
private int getNextLease() {
|
||||||
// set in runJob if found locally
|
// set in runJob if found locally
|
||||||
if (_leaseSet == null) {
|
if (_leaseSet == null || !_leaseSet.getReceivedAsReply()) {
|
||||||
_leaseSet = getContext().netDb().lookupLeaseSetLocally(_to.calculateHash());
|
_leaseSet = getContext().netDb().lookupLeaseSetLocally(_to.calculateHash());
|
||||||
if (_leaseSet == null) {
|
if (_leaseSet == null) {
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn(getJobId() + ": Lookup locally didn't find the leaseSet for " + _toString);
|
_log.warn(getJobId() + ": Lookup locally didn't find the leaseSet for " + _toString);
|
||||||
return MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
return MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
||||||
|
} else if (_leaseSet.getReceivedAsPublished()) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn(getJobId() + ": Only have RAP LS for " + _toString);
|
||||||
|
return MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,8 +592,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
|||||||
_log.warn("Unable to send to " + _toString + " because the sig type is unsupported");
|
_log.warn("Unable to send to " + _toString + " because the sig type is unsupported");
|
||||||
cause = MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION;
|
cause = MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION;
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldInfo())
|
||||||
_log.warn("Unable to send to " + _toString + " because we couldn't find their leaseSet");
|
_log.info("Unable to send to " + _toString + ", no LS found");
|
||||||
cause = MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
cause = MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,16 +116,16 @@ class HandleFloodfillDatabaseStoreMessageJob extends JobImpl {
|
|||||||
} else if (match.getEarliestLeaseDate() < ls.getEarliestLeaseDate()) {
|
} else if (match.getEarliestLeaseDate() < ls.getEarliestLeaseDate()) {
|
||||||
wasNew = true;
|
wasNew = true;
|
||||||
// If it is in our keyspace and we are talking to it
|
// If it is in our keyspace and we are talking to it
|
||||||
if (match.getReceivedAsPublished())
|
//if (match.getReceivedAsPublished())
|
||||||
ls.setReceivedAsPublished(true);
|
// ls.setReceivedAsPublished(true);
|
||||||
} else if (type != DatabaseEntry.KEY_TYPE_LEASESET &&
|
} else if (type != DatabaseEntry.KEY_TYPE_LEASESET &&
|
||||||
match.getType() != DatabaseEntry.KEY_TYPE_LEASESET) {
|
match.getType() != DatabaseEntry.KEY_TYPE_LEASESET) {
|
||||||
LeaseSet2 ls2 = (LeaseSet2) ls;
|
LeaseSet2 ls2 = (LeaseSet2) ls;
|
||||||
LeaseSet2 match2 = (LeaseSet2) match;
|
LeaseSet2 match2 = (LeaseSet2) match;
|
||||||
if (match2.getPublished() < ls2.getPublished()) {
|
if (match2.getPublished() < ls2.getPublished()) {
|
||||||
wasNew = true;
|
wasNew = true;
|
||||||
if (match.getReceivedAsPublished())
|
//if (match.getReceivedAsPublished())
|
||||||
ls.setReceivedAsPublished(true);
|
// ls.setReceivedAsPublished(true);
|
||||||
} else {
|
} else {
|
||||||
wasNew = false;
|
wasNew = false;
|
||||||
}
|
}
|
||||||
|
@ -602,9 +602,28 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {
|
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {
|
||||||
if (!_initialized) return;
|
if (!_initialized) return;
|
||||||
key = _blindCache.getHash(key);
|
key = _blindCache.getHash(key);
|
||||||
|
if (isNegativeCached(key))
|
||||||
|
return;
|
||||||
search(key, null, null, 20*1000, true, fromLocalDest);
|
search(key, null, null, 20*1000, true, fromLocalDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unconditionally lookup using the client's tunnels.
|
||||||
|
*
|
||||||
|
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory
|
||||||
|
* @param onFindJob may be null
|
||||||
|
* @param onFailedLookupJob may be null
|
||||||
|
* @since 0.9.47
|
||||||
|
*/
|
||||||
|
public void lookupLeaseSetRemotely(Hash key, Job onFindJob, Job onFailedLookupJob,
|
||||||
|
long timeoutMs, Hash fromLocalDest) {
|
||||||
|
if (!_initialized) return;
|
||||||
|
key = _blindCache.getHash(key);
|
||||||
|
if (isNegativeCached(key))
|
||||||
|
return;
|
||||||
|
search(key, onFindJob, onFailedLookupJob, timeoutMs, true, fromLocalDest);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use lookupDestination() if you don't need the LS or don't need it validated.
|
* Use lookupDestination() if you don't need the LS or don't need it validated.
|
||||||
*/
|
*/
|
||||||
@ -936,6 +955,16 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
rv = (LeaseSet)_ds.get(key);
|
rv = (LeaseSet)_ds.get(key);
|
||||||
if ( (rv != null) && (rv.equals(leaseSet)) ) {
|
if ( (rv != null) && (rv.equals(leaseSet)) ) {
|
||||||
// if it hasn't changed, no need to do anything
|
// if it hasn't changed, no need to do anything
|
||||||
|
// except copy over the flags
|
||||||
|
Hash to = leaseSet.getReceivedBy();
|
||||||
|
if (to != null) {
|
||||||
|
rv.setReceivedBy(to);
|
||||||
|
} else if (leaseSet.getReceivedAsReply()) {
|
||||||
|
rv.setReceivedAsReply();
|
||||||
|
}
|
||||||
|
if (leaseSet.getReceivedAsPublished()) {
|
||||||
|
rv.setReceivedAsPublished(true);
|
||||||
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
} catch (ClassCastException cce) {
|
} catch (ClassCastException cce) {
|
||||||
|
@ -125,7 +125,7 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
|
|||||||
// allow DSM of our own key (used by FloodfillVerifyStoreJob)
|
// allow DSM of our own key (used by FloodfillVerifyStoreJob)
|
||||||
// or other keys (used by IterativeSearchJob)
|
// or other keys (used by IterativeSearchJob)
|
||||||
// as long as there's no reply token (we will never set a reply token but an attacker might)
|
// as long as there's no reply token (we will never set a reply token but an attacker might)
|
||||||
((LeaseSet)dsm.getEntry()).setReceivedAsReply();
|
((LeaseSet)dsm.getEntry()).setReceivedBy(_client);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dsm.getEntry().isLeaseSet())
|
if (dsm.getEntry().isLeaseSet())
|
||||||
((LeaseSet)dsm.getEntry()).setReceivedAsReply();
|
((LeaseSet)dsm.getEntry()).setReceivedBy(_client);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DatabaseSearchReplyMessage.MESSAGE_TYPE:
|
case DatabaseSearchReplyMessage.MESSAGE_TYPE:
|
||||||
@ -264,7 +264,7 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
|
|||||||
// Or, it's a normal LS bundled with data and a MessageStatusMessage.
|
// Or, it's a normal LS bundled with data and a MessageStatusMessage.
|
||||||
|
|
||||||
// ... and inject it.
|
// ... and inject it.
|
||||||
((LeaseSet)dsm.getEntry()).setReceivedAsReply();
|
((LeaseSet)dsm.getEntry()).setReceivedBy(_client);
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("Storing garlic LS down tunnel for: " + dsm.getKey() + " sent to: " +
|
_log.info("Storing garlic LS down tunnel for: " + dsm.getKey() + " sent to: " +
|
||||||
(_client != null ? _client.toBase32() : "router"));
|
(_client != null ? _client.toBase32() : "router"));
|
||||||
|
Reference in New Issue
Block a user