/* This code is part of Freenet. It is distributed under the GNU General
* Public License, version 2 (or at your option any later version). See
* http://www.gnu.org/ for further details of the GPL. */
package freenet.io.comm;
import java.util.concurrent.atomic.AtomicLong;
import freenet.crypt.EntropySource;
import freenet.node.FNPPacketMangler;
import freenet.node.Node;
import freenet.node.NodeCrypto;
import freenet.node.PeerNode;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;
public class IncomingPacketFilterImpl implements IncomingPacketFilter {
private static volatile boolean logMINOR;
static {
Logger.registerLogThresholdCallback(new LogThresholdCallback() {
@Override
public void shouldUpdate() {
logMINOR = Logger.shouldLog(LogLevel.MINOR, IncomingPacketFilterImpl.class);
}
});
}
private FNPPacketMangler mangler;
private NodeCrypto crypto;
private Node node;
private final EntropySource fnpTimingSource;
public IncomingPacketFilterImpl(FNPPacketMangler mangler, Node node, NodeCrypto crypto) {
this.mangler = mangler;
this.node = node;
this.crypto = crypto;
fnpTimingSource = new EntropySource();
}
@Override
public boolean isDisconnected(PeerContext context) {
if(context == null) return false;
return !context.isConnected();
}
private static final AtomicLong successfullyDecodedPackets = new AtomicLong();
private static final AtomicLong failedDecodePackets = new AtomicLong();
public static long[] getDecodedPackets() {
if(!logMINOR) return null;
long decoded = successfullyDecodedPackets.get();
long failed = failedDecodePackets.get();
return new long[] { decoded, decoded+failed };
}
@Override
public DECODED process(byte[] buf, int offset, int length, Peer peer, long now) {
if(logMINOR) Logger.minor(this, "Packet length "+length+" from "+peer);
node.random.acceptTimerEntropy(fnpTimingSource, 0.25);
PeerNode opn = node.peers.getByPeer(peer, mangler);
if(opn != null) {
if(opn.handleReceivedPacket(buf, offset, length, now, peer)) {
if(logMINOR) successfullyDecodedPackets.incrementAndGet();
return DECODED.DECODED;
}
} else {
Logger.normal(this, "Got packet from unknown address");
}
DECODED decoded = mangler.process(buf, offset, length, peer, opn, now);
if(decoded == DECODED.DECODED) {
if(logMINOR) successfullyDecodedPackets.incrementAndGet();
} else if(decoded == DECODED.NOT_DECODED) {
for(PeerNode pn : crypto.getPeerNodes()) {
if(pn == opn) continue;
if(pn.handleReceivedPacket(buf, offset, length, now, peer)) {
if(logMINOR) successfullyDecodedPackets.incrementAndGet();
return DECODED.DECODED;
}
}
if(logMINOR) failedDecodePackets.incrementAndGet();
}
return decoded;
}
}