2006-02-24 jrandom
* Rounding calculation cleanup in the stats, and avoid an uncontested mutex (thanks ripple!) * SSU handshake cleanup to help force incompatible peers to stop nagging us by both not giving them an updated reference to us and by dropping future handshake packets from them.
This commit is contained in:
@ -187,10 +187,10 @@ public class Rate {
|
||||
// ok ok, lets coalesce
|
||||
|
||||
// how much were we off by? (so that we can sample down the measured values)
|
||||
double periodFactor = measuredPeriod / _period;
|
||||
_lastTotalValue = (_currentTotalValue == 0 ? 0.0D : _currentTotalValue / periodFactor);
|
||||
_lastEventCount = (_currentEventCount == 0 ? 0L : (long) (_currentEventCount / periodFactor));
|
||||
_lastTotalEventTime = (_currentTotalEventTime == 0 ? 0L : (long) (_currentTotalEventTime / periodFactor));
|
||||
double periodFactor = measuredPeriod / (double)_period;
|
||||
_lastTotalValue = _currentTotalValue / periodFactor;
|
||||
_lastEventCount = (long) (_currentEventCount / periodFactor);
|
||||
_lastTotalEventTime = (long) (_currentTotalEventTime / periodFactor);
|
||||
_lastCoalesceDate = now;
|
||||
|
||||
if (_lastTotalValue > _extremeTotalValue) {
|
||||
@ -237,10 +237,12 @@ public class Rate {
|
||||
*/
|
||||
public double getLastEventSaturation() {
|
||||
if ((_lastEventCount > 0) && (_lastTotalEventTime > 0)) {
|
||||
double eventTime = (double) _lastTotalEventTime / (double) _lastEventCount;
|
||||
/*double eventTime = (double) _lastTotalEventTime / (double) _lastEventCount;
|
||||
double maxEvents = _period / eventTime;
|
||||
double saturation = _lastEventCount / maxEvents;
|
||||
return saturation;
|
||||
*/
|
||||
return ((double)_lastTotalEventTime) / (double)_period;
|
||||
}
|
||||
|
||||
return 0.0D;
|
||||
|
@ -146,15 +146,15 @@ public class DecayingBloomFilter {
|
||||
for (int i = 0; i < _extenders.length; i++)
|
||||
DataHelper.xor(entry, offset, _extenders[i], 0, _extended, _entryBytes * (i+1), _entryBytes);
|
||||
|
||||
boolean seen = _current.member(_extended);
|
||||
seen = seen || _previous.member(_extended);
|
||||
boolean seen = _current.locked_member(_extended);
|
||||
seen = seen || _previous.locked_member(_extended);
|
||||
if (seen) {
|
||||
_currentDuplicates++;
|
||||
return true;
|
||||
} else {
|
||||
if (addIfNew) {
|
||||
_current.insert(_extended);
|
||||
_previous.insert(_extended);
|
||||
_current.locked_insert(_extended);
|
||||
_previous.locked_insert(_extended);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,4 +1,11 @@
|
||||
$Id: history.txt,v 1.417 2006/02/23 03:08:37 jrandom Exp $
|
||||
$Id: history.txt,v 1.418 2006/02/23 09:38:41 jrandom Exp $
|
||||
|
||||
2006-02-24 jrandom
|
||||
* Rounding calculation cleanup in the stats, and avoid an uncontested
|
||||
mutex (thanks ripple!)
|
||||
* SSU handshake cleanup to help force incompatible peers to stop nagging
|
||||
us by both not giving them an updated reference to us and by dropping
|
||||
future handshake packets from them.
|
||||
|
||||
2006-02-23 jrandom
|
||||
* Increase the SSU retransmit ceiling (for slow links)
|
||||
|
@ -1014,8 +1014,8 @@ public class Router {
|
||||
class CoalesceStatsJob extends JobImpl {
|
||||
public CoalesceStatsJob(RouterContext ctx) {
|
||||
super(ctx);
|
||||
ctx.statManager().createRateStat("bw.receiveBps", "How fast we receive data", "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
||||
ctx.statManager().createRateStat("bw.sendBps", "How fast we send data", "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
||||
ctx.statManager().createRateStat("bw.receiveBps", "How fast we receive data (in KBps)", "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
||||
ctx.statManager().createRateStat("bw.sendBps", "How fast we send data (in KBps)", "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
|
||||
ctx.statManager().createRateStat("router.activePeers", "How many peers we are actively talking with", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
|
||||
ctx.statManager().createRateStat("router.highCapacityPeers", "How many high capacity peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
|
||||
ctx.statManager().createRateStat("router.fastPeers", "How many fast peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 });
|
||||
@ -1029,8 +1029,8 @@ class CoalesceStatsJob extends JobImpl {
|
||||
Rate rate = receiveRate.getRate(60*1000);
|
||||
if (rate != null) {
|
||||
double bytes = rate.getLastTotalValue();
|
||||
double bps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
getContext().statManager().addRateData("bw.receiveBps", (long)bps, 60*1000);
|
||||
double KBps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
getContext().statManager().addRateData("bw.receiveBps", (long)KBps, 60*1000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1039,8 +1039,8 @@ class CoalesceStatsJob extends JobImpl {
|
||||
Rate rate = sendRate.getRate(60*1000);
|
||||
if (rate != null) {
|
||||
double bytes = rate.getLastTotalValue();
|
||||
double bps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
getContext().statManager().addRateData("bw.sendBps", (long)bps, 60*1000);
|
||||
double KBps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
getContext().statManager().addRateData("bw.sendBps", (long)KBps, 60*1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.358 $ $Date: 2006/02/22 20:48:47 $";
|
||||
public final static String ID = "$Revision: 1.359 $ $Date: 2006/02/23 09:38:40 $";
|
||||
public final static String VERSION = "0.6.1.11";
|
||||
public final static long BUILD = 3;
|
||||
public final static long BUILD = 4;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@ -16,6 +16,8 @@ import net.i2p.data.RouterIdentity;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.data.Signature;
|
||||
import net.i2p.data.i2np.DatabaseStoreMessage;
|
||||
import net.i2p.data.i2np.DeliveryStatusMessage;
|
||||
import net.i2p.data.i2np.I2NPMessage;
|
||||
import net.i2p.router.CommSystemFacade;
|
||||
import net.i2p.router.OutNetMessage;
|
||||
import net.i2p.router.Router;
|
||||
@ -440,7 +442,41 @@ public class EstablishmentManager {
|
||||
_transport.inboundConnectionReceived();
|
||||
|
||||
_context.statManager().addRateData("udp.inboundEstablishTime", state.getLifetime(), 0);
|
||||
sendOurInfo(peer, true);
|
||||
sendInboundComplete(peer);
|
||||
}
|
||||
|
||||
/**
|
||||
* dont send our info immediately, just send a small data packet, and 5-10s later,
|
||||
* if the peer isnt shitlisted, *then* send them our info. this will help kick off
|
||||
* the oldnet
|
||||
*/
|
||||
private void sendInboundComplete(PeerState peer) {
|
||||
SimpleTimer.getInstance().addEvent(new PublishToNewInbound(peer), 10*1000);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Completing to the peer after confirm: " + peer);
|
||||
DeliveryStatusMessage dsm = new DeliveryStatusMessage(_context);
|
||||
dsm.setArrival(Router.NETWORK_ID); // overloaded, sure, but future versions can check this
|
||||
dsm.setMessageExpiration(dsm.getArrival()+10*1000);
|
||||
dsm.setMessageId(_context.random().nextLong(I2NPMessage.MAX_ID_VALUE));
|
||||
_transport.send(dsm, peer);
|
||||
}
|
||||
private class PublishToNewInbound implements SimpleTimer.TimedEvent {
|
||||
private PeerState _peer;
|
||||
public PublishToNewInbound(PeerState peer) { _peer = peer; }
|
||||
public void timeReached() {
|
||||
Hash peer = _peer.getRemotePeer();
|
||||
if ((peer != null) && (!_context.shitlist().isShitlisted(peer))) {
|
||||
// ok, we are fine with them, send them our latest info
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Publishing to the peer after confirm plus delay (without shitlist): " + peer.toBase64());
|
||||
sendOurInfo(_peer, true);
|
||||
} else {
|
||||
// nuh uh. fuck 'em.
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("NOT publishing to the peer after confirm plus delay (WITH shitlist): " + (peer != null ? peer.toBase64() : "unknown"));
|
||||
}
|
||||
_peer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +58,9 @@ public class PacketHandler {
|
||||
_context.statManager().createRateStat("udp.droppedInvalidUnkown", "How old the packet we dropped due to invalidity (unkown type) was", "udp", new long[] { 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.droppedInvalidReestablish", "How old the packet we dropped due to invalidity (doesn't use existing key, not an establishment) was", "udp", new long[] { 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.droppedInvalidEstablish", "How old the packet we dropped due to invalidity (establishment, bad key) was", "udp", new long[] { 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.droppedInvalidEstablish.inbound", "How old the packet we dropped due to invalidity (even though we have an active inbound establishment with the peer) was", "udp", new long[] { 60*1000, 10*60*1000 });
|
||||
_context.statManager().createRateStat("udp.droppedInvalidEstablish.outbound", "How old the packet we dropped due to invalidity (even though we have an active outbound establishment with the peer) was", "udp", new long[] { 60*1000, 10*60*1000 });
|
||||
_context.statManager().createRateStat("udp.droppedInvalidEstablish.new", "How old the packet we dropped due to invalidity (even though we do not have any active establishment with the peer) was", "udp", new long[] { 60*1000, 10*60*1000 });
|
||||
_context.statManager().createRateStat("udp.droppedInvalidInboundEstablish", "How old the packet we dropped due to invalidity (inbound establishment, bad key) was", "udp", new long[] { 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.droppedInvalidSkew", "How skewed the packet we dropped due to invalidity (valid except bad skew) was", "udp", new long[] { 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.packetDequeueTime", "How long it takes the UDPReader to pull a packet off the inbound packet queue (when its slow)", "udp", new long[] { 10*60*1000, 60*60*1000 });
|
||||
@ -90,6 +93,13 @@ public class PacketHandler {
|
||||
}
|
||||
return rv.toString();
|
||||
}
|
||||
|
||||
/** the packet is from a peer we are establishing an outbound con to, but failed validation, so fallback */
|
||||
private static final short OUTBOUND_FALLBACK = 1;
|
||||
/** the packet is from a peer we are establishing an inbound con to, but failed validation, so fallback */
|
||||
private static final short INBOUND_FALLBACK = 2;
|
||||
/** the packet is not from anyone we know */
|
||||
private static final short NEW_PEER = 3;
|
||||
|
||||
private class Handler implements Runnable {
|
||||
private UDPPacketReader _reader;
|
||||
@ -106,6 +116,7 @@ public class PacketHandler {
|
||||
UDPPacket packet = _endpoint.receive();
|
||||
_state = 3;
|
||||
if (packet == null) continue; // keepReading is probably false...
|
||||
|
||||
packet.received();
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Received the packet " + packet);
|
||||
@ -202,7 +213,7 @@ public class PacketHandler {
|
||||
_log.debug("Packet received is not for an inbound or outbound establishment");
|
||||
// ok, not already known establishment, try as a new one
|
||||
_state = 15;
|
||||
receivePacket(reader, packet);
|
||||
receivePacket(reader, packet, NEW_PEER);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -264,13 +275,24 @@ public class PacketHandler {
|
||||
_state = 26;
|
||||
}
|
||||
|
||||
private void receivePacket(UDPPacketReader reader, UDPPacket packet) {
|
||||
private void receivePacket(UDPPacketReader reader, UDPPacket packet, short peerType) {
|
||||
_state = 27;
|
||||
boolean isValid = packet.validate(_transport.getIntroKey());
|
||||
if (!isValid) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Invalid introduction packet received: " + packet, new Exception("path"));
|
||||
_context.statManager().addRateData("udp.droppedInvalidEstablish", packet.getLifetime(), packet.getExpiration());
|
||||
switch (peerType) {
|
||||
case INBOUND_FALLBACK:
|
||||
_context.statManager().addRateData("udp.droppedInvalidEstablish.inbound", packet.getLifetime(), packet.getTimeSinceReceived());
|
||||
break;
|
||||
case OUTBOUND_FALLBACK:
|
||||
_context.statManager().addRateData("udp.droppedInvalidEstablish.outbound", packet.getLifetime(), packet.getTimeSinceReceived());
|
||||
break;
|
||||
case NEW_PEER:
|
||||
_context.statManager().addRateData("udp.droppedInvalidEstablish.new", packet.getLifetime(), packet.getTimeSinceReceived());
|
||||
break;
|
||||
}
|
||||
_state = 28;
|
||||
return;
|
||||
} else {
|
||||
@ -322,7 +344,7 @@ public class PacketHandler {
|
||||
// ok, we couldn't handle it with the established stuff, so fall back
|
||||
// on earlier state packets
|
||||
_state = 34;
|
||||
receivePacket(reader, packet);
|
||||
receivePacket(reader, packet, INBOUND_FALLBACK);
|
||||
} else {
|
||||
_context.statManager().addRateData("udp.droppedInvalidInboundEstablish", packet.getLifetime(), packet.getExpiration());
|
||||
}
|
||||
@ -373,7 +395,7 @@ public class PacketHandler {
|
||||
// ok, we couldn't handle it with the established stuff, so fall back
|
||||
// on earlier state packets
|
||||
_state = 41;
|
||||
receivePacket(reader, packet);
|
||||
receivePacket(reader, packet, OUTBOUND_FALLBACK);
|
||||
_state = 42;
|
||||
}
|
||||
|
||||
@ -413,7 +435,7 @@ public class PacketHandler {
|
||||
_state = 45;
|
||||
RemoteHostId from = packet.getRemoteHost();
|
||||
_state = 46;
|
||||
|
||||
|
||||
switch (reader.readPayloadType()) {
|
||||
case UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST:
|
||||
_state = 47;
|
||||
|
@ -47,6 +47,7 @@ public class UDPReceiver {
|
||||
_context.statManager().createRateStat("udp.droppedInboundProbabalistically", "How many packet we drop probabalistically (to simulate failures)", "udp", new long[] { 60*1000, 5*60*1000, 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.acceptedInboundProbabalistically", "How many packet we accept probabalistically (to simulate failures)", "udp", new long[] { 60*1000, 5*60*1000, 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.receiveHolePunch", "How often we receive a NAT hole punch", "udp", new long[] { 60*1000, 5*60*1000, 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("udp.ignorePacketFromDroplist", "Packet lifetime for those dropped on the drop list", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
}
|
||||
|
||||
public void startup() {
|
||||
@ -124,6 +125,15 @@ public class UDPReceiver {
|
||||
private final int doReceive(UDPPacket packet) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Received: " + packet);
|
||||
|
||||
RemoteHostId from = packet.getRemoteHost();
|
||||
if (_transport.isInDropList(from)) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Ignoring packet from the drop-listed peer: " + from);
|
||||
_context.statManager().addRateData("udp.ignorePacketFromDroplist", packet.getLifetime(), 0);
|
||||
packet.release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
packet.enqueue();
|
||||
boolean rejected = false;
|
||||
|
@ -78,6 +78,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
/** shared slow bid for unconnected peers when we want to prefer UDP */
|
||||
private TransportBid _slowPreferredBid;
|
||||
|
||||
/** list of RemoteHostId for peers whose packets we want to drop outright */
|
||||
private List _dropList;
|
||||
|
||||
private static final int DROPLIST_PERIOD = 10*60*1000;
|
||||
private static final int MAX_DROPLIST_SIZE = 256;
|
||||
|
||||
public static final String STYLE = "SSU";
|
||||
public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort";
|
||||
|
||||
@ -124,6 +130,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
_log = ctx.logManager().getLog(UDPTransport.class);
|
||||
_peersByIdent = new HashMap(128);
|
||||
_peersByRemoteHost = new HashMap(128);
|
||||
_dropList = new ArrayList(256);
|
||||
_endpoint = null;
|
||||
|
||||
TimedWeightedPriorityMessageQueue mq = new TimedWeightedPriorityMessageQueue(ctx, PRIORITY_LIMITS, PRIORITY_WEIGHT, this);
|
||||
@ -572,11 +579,25 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
+ " because they are in the wrong net");
|
||||
}
|
||||
*/
|
||||
_context.shitlist().shitlistRouter(dsm.getRouterInfo().getIdentity().calculateHash(), "Part of the wrong network");
|
||||
dropPeer(dsm.getRouterInfo().getIdentity().calculateHash());
|
||||
Hash peerHash = dsm.getRouterInfo().getIdentity().calculateHash();
|
||||
PeerState peer = getPeerState(peerHash);
|
||||
if (peer != null) {
|
||||
RemoteHostId remote = peer.getRemoteHostId();
|
||||
boolean added = false;
|
||||
synchronized (_dropList) {
|
||||
if (!_dropList.contains(remote)) {
|
||||
while (_dropList.size() > MAX_DROPLIST_SIZE)
|
||||
_dropList.remove(0);
|
||||
_dropList.add(remote);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
if (added) SimpleTimer.getInstance().addEvent(new RemoveDropList(remote), DROPLIST_PERIOD);
|
||||
}
|
||||
_context.shitlist().shitlistRouter(peerHash, "Part of the wrong network");
|
||||
dropPeer(peerHash);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Dropping the peer " + dsm.getRouterInfo().getIdentity().calculateHash().toBase64()
|
||||
+ " because they are in the wrong net");
|
||||
_log.warn("Dropping the peer " + peerHash.toBase64() + " because they are in the wrong net");
|
||||
return;
|
||||
} else {
|
||||
if (dsm.getRouterInfo() != null) {
|
||||
@ -597,6 +618,17 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
peer.expireInboundMessages();
|
||||
}
|
||||
|
||||
private class RemoveDropList implements SimpleTimer.TimedEvent {
|
||||
private RemoteHostId _peer;
|
||||
public RemoveDropList(RemoteHostId peer) { _peer = peer; }
|
||||
public void timeReached() {
|
||||
synchronized (_dropList) {
|
||||
_dropList.remove(_peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInDropList(RemoteHostId peer) { synchronized (_dropList) { return _dropList.contains(peer); } }
|
||||
|
||||
void dropPeer(Hash peer) {
|
||||
PeerState state = getPeerState(peer);
|
||||
|
Reference in New Issue
Block a user