diff --git a/history.txt b/history.txt index 1279ffe7da..afce958517 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,15 @@ +2008-04-16 zzz + * SSU/Reachability: + - Extend shitlist time from 4-8m to 40-60m + - Add some shitlist logging + - Don't shitlist twice when unreachable on all transports + - Exclude netDb-listed unreachable peers from inbound tunnels; + this won't help much since there are very few of these now + - Remove 10s delay on inbound UDP connections used for the + 0.6.1.10 transition + - Track and display UDP connection direction on peers.jsp + - Show shitlist status in-line on profiles.jsp + 2008-04-15 zzz * SSU Reachability/PeerTestManager: - Back out strict peer ordering until we fix SSU diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index b4c410afba..1bdcecca63 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -17,7 +17,7 @@ import net.i2p.CoreVersion; public class RouterVersion { public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $"; public final static String VERSION = "0.6.1.32"; - public final static long BUILD = 17; + public final static long BUILD = 18; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java index 80febdeea7..43c24a2e66 100644 --- a/router/java/src/net/i2p/router/Shitlist.java +++ b/router/java/src/net/i2p/router/Shitlist.java @@ -37,7 +37,7 @@ public class Shitlist { Set transports; } - public final static long SHITLIST_DURATION_MS = 4*60*1000; // 4 minute shitlist + public final static long SHITLIST_DURATION_MS = 40*60*1000; // 40 minute shitlist public Shitlist(RouterContext context) { _context = context; @@ -72,6 +72,8 @@ public class Shitlist { if (prof != null) prof.unshitlist(); _context.messageHistory().unshitlist(peer); + if (_log.shouldLog(Log.INFO)) + _log.info("Unshitlisting router (expired) " + peer.toBase64()); } requeue(30*1000); @@ -152,12 +154,13 @@ public class Shitlist { public void unshitlistRouter(Hash peer, String transport) { unshitlistRouter(peer, true, transport); } private void unshitlistRouter(Hash peer, boolean realUnshitlist, String transport) { if (peer == null) return; - if (_log.shouldLog(Log.INFO)) - _log.info("Unshitlisting router " + peer.toBase64() + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Calling unshitlistRouter " + peer.toBase64() + (transport != null ? "/" + transport : "")); boolean fully = false; + Entry e; synchronized (_entries) { - Entry e = (Entry)_entries.remove(peer); + e = (Entry)_entries.remove(peer); if ( (e == null) || (e.transports == null) || (transport == null) || (e.transports.size() <= 1) ) { // fully unshitlisted fully = true; @@ -176,6 +179,9 @@ public class Shitlist { prof.unshitlist(); } _context.messageHistory().unshitlist(peer); + if (_log.shouldLog(Log.INFO) && e != null) + _log.info("Unshitlisting router " + peer.toBase64() + + (transport != null ? "/" + transport : "")); } } @@ -209,6 +215,8 @@ public class Shitlist { if (prof != null) prof.unshitlist(); _context.messageHistory().unshitlist(peer); + if (_log.shouldLog(Log.INFO)) + _log.info("Unshitlisting router (expired) " + peer.toBase64()); } return rv; diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java index 5b1af57a7d..ebc87f0608 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java @@ -134,7 +134,10 @@ class ProfileOrganizerRenderer { buf.append(""); buf.append("").append(num(prof.getCapacityValue())).append(""); buf.append("").append(num(prof.getIntegrationValue())).append(""); - buf.append("").append(prof.getIsFailing()).append(""); + buf.append(""); + if (_context.shitlist().isShitlisted(peer)) buf.append("Shitlist"); + if (prof.getIsFailing()) buf.append(" Failing"); + buf.append(" "); //buf.append("profile.txt "); //buf.append(" netDb"); buf.append("netDb"); diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index 0d29bb87bb..bc622db4c5 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -259,6 +259,9 @@ public class TransportManager implements TransportEventListener { Transport t = (Transport)_transports.get(i); if (t.isUnreachable(peer)) { unreachableTransports++; + // this keeps GetBids() from shitlisting for "no common transports" + // right after we shitlisted for "unreachable on any transport" below... + msg.transportFailed(t.getStyle()); continue; } if (failedTransports.contains(t.getStyle())) { diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java index a6f9d13b75..5e46476e76 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -431,6 +431,7 @@ public class EstablishmentManager { peer.setRemotePeer(remote.calculateHash()); peer.setWeRelayToThemAs(state.getSentRelayTag()); peer.setTheyRelayToUsAs(0); + peer.setInbound(); if (_log.shouldLog(Log.DEBUG)) _log.debug("Handle completely established (inbound): " + state.getRemoteHostId().toString() @@ -451,9 +452,16 @@ public class EstablishmentManager { * 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 + * The "oldnet" was < 0.6.1.10, it is long gone. + * The delay really slows down the network. + * The peer is unshitlisted and marked reachable by addRemotePeerState() which calls markReachable() + * so the check below is fairly pointless. + * If for some strange reason an oldnet router (NETWORK_ID == 1) does show up, + * it's handled in UDPTransport.messageReceived() + * (where it will get dropped, marked unreachable and shitlisted at that time). */ private void sendInboundComplete(PeerState peer) { - SimpleTimer.getInstance().addEvent(new PublishToNewInbound(peer), 10*1000); + // 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); @@ -461,6 +469,7 @@ public class EstablishmentManager { dsm.setMessageExpiration(_context.clock().now()+10*1000); dsm.setMessageId(_context.random().nextLong(I2NPMessage.MAX_ID_VALUE)); _transport.send(dsm, peer); + SimpleTimer.getInstance().addEvent(new PublishToNewInbound(peer), 0); } private class PublishToNewInbound implements SimpleTimer.TimedEvent { private PeerState _peer; diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java index 53ab46e458..7aaff0ac99 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -190,7 +190,9 @@ public class PeerState { private volatile int _concurrentMessagesActive = 0; /** how many concurrency rejections have we had in a row */ private volatile int _consecutiveRejections = 0; - + /** is it inbound? **/ + private boolean _isInbound; + private static final int DEFAULT_SEND_WINDOW_BYTES = 8*1024; private static final int MINIMUM_WINDOW_BYTES = DEFAULT_SEND_WINDOW_BYTES; private static final int MAX_SEND_WINDOW_BYTES = 1024*1024; @@ -268,6 +270,7 @@ public class PeerState { _inboundMessages = new HashMap(8); _outboundMessages = new ArrayList(32); _dead = false; + _isInbound = false; _context.statManager().createRateStat("udp.congestionOccurred", "How large the cwin was when congestion occurred (duration == sendBps)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 }); _context.statManager().createRateStat("udp.congestedRTO", "retransmission timeout after congestion (duration == rtt dev)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 }); _context.statManager().createRateStat("udp.sendACKPartial", "Number of partial ACKs sent (duration == number of full ACKs in that ack packet)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 }); @@ -553,6 +556,8 @@ public class PeerState { public int getConcurrentSends() { return _concurrentMessagesActive; } public int getConcurrentSendWindow() { return _concurrentMessagesAllowed; } public int getConsecutiveSendRejections() { return _consecutiveRejections; } + public boolean isInbound() { return _isInbound; } + public void setInbound() { _isInbound = true; } /** we received the message specified completely */ public void messageFullyReceived(Long messageId, int bytes) { messageFullyReceived(messageId, bytes, false); } diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 38f6ee7d30..77c1e3b7cd 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -625,6 +625,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } } markUnreachable(peerHash); + _context.shitlist().shitlistRouter(peerHash, "Part of the wrong network"); //_context.shitlist().shitlistRouter(peerHash, "Part of the wrong network", STYLE); dropPeer(peerHash, false, "wrong network"); if (_log.shouldLog(Log.WARN)) @@ -1673,14 +1674,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority buf.append(port); */ buf.append(" "); + if (peer.isInbound()) + buf.append("> "); + else + buf.append("< "); if (peer.getWeRelayToThemAs() > 0) - buf.append(">"); + buf.append("^"); else buf.append(" "); if (peer.getTheyRelayToUsAs() > 0) - buf.append("<"); - else - buf.append(" "); + buf.append("v"); boolean appended = false; if (_activeThrottle.isChoked(peer.getRemotePeer())) { @@ -1872,7 +1875,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } private static final String KEY = "" + - "peer: the remote peer (< means they offer to introduce us, > means we offer to introduce them)
\n" + + "peer: the remote peer (< inbound, > outbound, v means they offer to introduce us, ^ means we offer to introduce them)
\n" + "idle: the idle time is how long since a packet has been received or sent
\n" + "in/out: the rates show a smoothed inbound and outbound transfer rate (KBytes per second)
\n" + "up: the uptime is how long ago this session was established
\n" + diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java index 3d4a0b9a5c..97a1299785 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java @@ -152,16 +152,26 @@ public abstract class TunnelPeerSelector { // isn't safe, since they may publish one set of routerInfo to us and another to // other peers. the defaults for filterUnreachable has always been to return false, // but might as well make it explicit with a "false &&" - - if (false && filterUnreachable(ctx, isInbound, isExploratory)) { + // + // Unreachable peers at the inbound gateway is a major cause of problems. + // Due to a bug in SSU peer testing in 0.6.1.32 and earlier, peers don't know + // if they are unreachable, so this won't help much. As of 0.6.1.33 we should have + // lots of unreachables, so enable this for now. + // We could just try and exclude them as the inbound gateway but that's harder + // (and even worse for anonymity?). + // + // Defaults changed to true for inbound only in filterUnreachable below. + + Set peers = new HashSet(1); + // if (false && filterUnreachable(ctx, isInbound, isExploratory)) { + if (filterUnreachable(ctx, isInbound, isExploratory)) { List caps = ctx.peerManager().getPeersByCapability(Router.CAPABILITY_UNREACHABLE); - if (caps == null) return new HashSet(0); - HashSet rv = new HashSet(caps); - return rv; - } else if (filterSlow(ctx, isInbound, isExploratory)) { + if (caps != null) + peers.addAll(caps); + } + if (filterSlow(ctx, isInbound, isExploratory)) { Log log = ctx.logManager().getLog(TunnelPeerSelector.class); char excl[] = getExcludeCaps(ctx); - Set peers = new HashSet(1); if (excl != null) { FloodfillNetworkDatabaseFacade fac = (FloodfillNetworkDatabaseFacade)ctx.netDb(); List known = fac.getKnownRouterData(); @@ -268,10 +278,8 @@ public abstract class TunnelPeerSelector { } */ } - return peers; - } else { - return new HashSet(1); } + return peers; } public static boolean shouldExclude(RouterContext ctx, RouterInfo peer) { @@ -375,10 +383,11 @@ public abstract class TunnelPeerSelector { private static final String PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "router.inboundExploratoryExcludeUnreachable"; private static final String PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = "router.inboundClientExcludeUnreachable"; - private static final boolean DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false; - private static final boolean DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = false; - private static final boolean DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false; - private static final boolean DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = false; + private static final String DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "false"; + private static final String DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = "false"; + // see comments at getExclude() above + private static final String DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "true"; + private static final String DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = "true"; protected boolean filterUnreachable(RouterContext ctx, boolean isInbound, boolean isExploratory) { boolean def = false; @@ -386,14 +395,14 @@ public abstract class TunnelPeerSelector { if (isExploratory) if (isInbound) - val = ctx.getProperty(PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE); + val = ctx.getProperty(PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE, DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE); else - val = ctx.getProperty(PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE); + val = ctx.getProperty(PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE, DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE); else if (isInbound) - val = ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE); + val = ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE); else - val = ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE); + val = ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE); boolean rv = (val != null ? Boolean.valueOf(val).booleanValue() : def); //System.err.println("Filter unreachable? " + rv + " (inbound? " + isInbound + ", exploratory? " + isExploratory);