}
long id = m.getLong(DMT.UID);
ByteCounter ctr = isSSK ? node.nodeStats.sskRequestCtr : node.nodeStats.chkRequestCtr;
short htl = m.getShort(DMT.HTL);
if(htl <= 0) htl = 1;
Key key = (Key) m.getObject(DMT.FREENET_ROUTING_KEY);
boolean realTimeFlag = DMT.getRealTimeFlag(m);
final RequestTag tag = new RequestTag(isSSK, RequestTag.START.REMOTE, source, realTimeFlag, id, node);
if(!tracker.lockUID(id, isSSK, false, false, false, realTimeFlag, tag)) {
if(logMINOR) Logger.minor(this, "Could not lock ID "+id+" -> rejecting (already running)");
Message rejected = DMT.createFNPRejectedLoop(id);
try {
source.sendAsync(rejected, null, ctr);
} catch (NotConnectedException e) {
Logger.normal(this, "Rejecting request from "+source.getPeer()+": "+e);
}
node.failureTable.onFinalFailure(key, null, htl, htl, -1, -1, source);
return;
} else {
if(logMINOR) Logger.minor(this, "Locked "+id);
}
// There are at least 2 threads that call this function.
// DO NOT reuse the meta object, unless on a per-thread basis.
// Object allocation is pretty cheap in modern Java anyway...
// If we do reuse it, call reset().
BlockMetadata meta = new BlockMetadata();
KeyBlock block = node.fetch(key, false, false, false, false, meta);
if(block != null)
tag.setNotRoutedOnwards();
RejectReason rejectReason = nodeStats.shouldRejectRequest(!isSSK, false, isSSK, false, false, source, block != null, false, realTimeFlag, tag);
if(rejectReason != null) {
// can accept 1 CHK request every so often, but not with SSKs because they aren't throttled so won't sort out bwlimitDelayTime, which was the whole reason for accepting them when overloaded...
Logger.normal(this, "Rejecting "+(isSSK ? "SSK" : "CHK")+" request from "+source.getPeer()+" preemptively because "+rejectReason);
Message rejected = DMT.createFNPRejectedOverload(id, true, true, realTimeFlag);
if(rejectReason.soft)
rejected.addSubMessage(DMT.createFNPRejectIsSoft());
try {
source.sendAsync(rejected, null, ctr);
} catch (NotConnectedException e) {
Logger.normal(this, "Rejecting (overload) data request from "+source.getPeer()+": "+e);
}
tag.setRejected();
tag.unlockHandler(rejectReason.soft);
// Do not tell failure table.
// Otherwise an attacker can flood us with requests very cheaply and purge our
// failure table even though we didn't accept any of them.
return;
}
nodeStats.reportIncomingRequestLocation(key.toNormalizedDouble());
//if(!node.lockUID(id)) return false;
boolean needsPubKey = false;
if(key instanceof NodeSSK)
needsPubKey = m.getBoolean(DMT.NEED_PUB_KEY);
RequestHandler rh = new RequestHandler(source, id, node, htl, key, tag, block, realTimeFlag, needsPubKey);