* Reintroduce NTCP backlog pushback, with switch back to

previous tunnel when no longer backlogged
    * Catch an nio exception in an NTCP logging statement if loglevel is WARN
    * IRC Proxy: terminate all messages with \r\n (thanks TrivialPursuit!)
This commit is contained in:
zzz
2008-02-26 19:33:11 +00:00
parent bc7ab39131
commit bc7bd628db
5 changed files with 70 additions and 19 deletions

View File

@ -164,7 +164,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("inbound: "+outmsg); _log.info("inbound: "+outmsg);
} }
outmsg=outmsg+"\n"; outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1")); output.write(outmsg.getBytes("ISO-8859-1"));
} else { } else {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
@ -238,7 +238,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("outbound: "+outmsg); _log.info("outbound: "+outmsg);
} }
outmsg=outmsg+"\n"; outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1")); output.write(outmsg.getBytes("ISO-8859-1"));
} else { } else {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))

View File

@ -1,3 +1,9 @@
2008-02-26 zzz
* Reintroduce NTCP backlog pushback, with switch back to
previous tunnel when no longer backlogged
* Catch an nio exception in an NTCP logging statement if loglevel is WARN
* IRC Proxy: terminate all messages with \r\n (thanks TrivialPursuit!)
2008-02-21 zzz 2008-02-21 zzz
* Raise inbound default bandwidth to 32KBps * Raise inbound default bandwidth to 32KBps
* Fix config.jsp that showed 0KBps share bandwidth by default * Fix config.jsp that showed 0KBps share bandwidth by default

View File

@ -17,7 +17,7 @@ import net.i2p.CoreVersion;
public class RouterVersion { public class RouterVersion {
public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $"; public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $";
public final static String VERSION = "0.6.1.31"; public final static String VERSION = "0.6.1.31";
public final static long BUILD = 6; public final static long BUILD = 7;
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID); System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -255,6 +255,9 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
return false; return false;
} }
// Right here is where we should use a persistent lease and caching like
// we do for outbound tunnel selection below???
// randomize the ordering (so leases with equal # of failures per next // randomize the ordering (so leases with equal # of failures per next
// sort are randomly ordered) // sort are randomly ordered)
Collections.shuffle(leases); Collections.shuffle(leases);
@ -435,39 +438,79 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
} }
} }
/**
* Clean out old tunnels from a set.
* Caller must synchronize on tc.
*/
private void cleanTunnelCache(HashMap tc) {
List deleteList = new ArrayList();
for (Iterator iter = tc.keySet().iterator(); iter.hasNext(); ) {
Destination dest = (Destination) iter.next();
TunnelInfo tunnel = (TunnelInfo) tc.get(dest);
if (!getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel))
deleteList.add(dest);
}
for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) {
Destination dest = (Destination) iter.next();
tc.remove(dest);
}
}
/** /**
* Use the same outbound tunnel as we did for the same destination previously, * Use the same outbound tunnel as we did for the same destination previously,
* if possible, to keep the streaming lib happy * if possible, to keep the streaming lib happy
* Use two caches - although a cache of a list of tunnels per dest might be
* more elegant.
* Key the caches just on the dest, not on source+dest, as different sources
* simultaneously talking to the same dest is probably rare enough
* to not bother separating out.
* *
*/ */
private static HashMap _tunnelCache = new HashMap(); private static HashMap _tunnelCache = new HashMap();
private static HashMap _backloggedTunnelCache = new HashMap();
private static long _cleanTime = 0; private static long _cleanTime = 0;
private TunnelInfo selectOutboundTunnel(Destination to) { private TunnelInfo selectOutboundTunnel(Destination to) {
TunnelInfo tunnel; TunnelInfo tunnel;
long now = getContext().clock().now(); long now = getContext().clock().now();
synchronized (_tunnelCache) { synchronized (_tunnelCache) {
if (now - _cleanTime > 5*60*1000) { // clean out periodically if (now - _cleanTime > 5*60*1000) { // clean out periodically
List deleteList = new ArrayList(); cleanTunnelCache(_tunnelCache);
for (Iterator iter = _tunnelCache.keySet().iterator(); iter.hasNext(); ) { cleanTunnelCache(_backloggedTunnelCache);
Destination dest = (Destination) iter.next();
tunnel = (TunnelInfo) _tunnelCache.get(dest);
if (!getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel))
deleteList.add(dest);
}
for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) {
Destination dest = (Destination) iter.next();
_tunnelCache.remove(dest);
}
_cleanTime = now; _cleanTime = now;
} }
/**
* If old tunnel is valid and no longer backlogged, use it.
* This prevents an active anonymity attack, where a peer could tell
* if you were the originator by backlogging the tunnel, then removing the
* backlog and seeing if traffic came back or not.
*/
tunnel = (TunnelInfo) _backloggedTunnelCache.get(to);
if (tunnel != null) {
if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) {
if (!getContext().commSystem().isBacklogged(tunnel.getPeer(1))) {
if (_log.shouldLog(Log.WARN))
_log.warn("Switching back to tunnel " + tunnel + " for dest " + to.calculateHash().toBase64());
_backloggedTunnelCache.remove(to);
_tunnelCache.put(to, tunnel);
return tunnel;
} // else still backlogged
} else // no longer valid
_backloggedTunnelCache.remove(to);
}
// Use the same tunnel unless backlogged
tunnel = (TunnelInfo) _tunnelCache.get(to); tunnel = (TunnelInfo) _tunnelCache.get(to);
if (tunnel != null) { if (tunnel != null) {
if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) {
return(tunnel); if (tunnel.getLength() <= 1 || !getContext().commSystem().isBacklogged(tunnel.getPeer(1)))
else return tunnel;
_tunnelCache.remove(to); // backlogged
if (_log.shouldLog(Log.WARN))
_log.warn("Switching from backlogged " + tunnel + " for dest " + to.calculateHash().toBase64());
_backloggedTunnelCache.put(to, tunnel);
} // else no longer valid
_tunnelCache.remove(to);
} }
// Pick a new tunnel
tunnel = selectOutboundTunnel(); tunnel = selectOutboundTunnel();
if (tunnel != null) if (tunnel != null)
_tunnelCache.put(to, tunnel); _tunnelCache.put(to, tunnel);

View File

@ -325,10 +325,12 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener {
int writeBufs = 0; int writeBufs = 0;
synchronized (_writeBufs) { writeBufs = _writeBufs.size(); } synchronized (_writeBufs) { writeBufs = _writeBufs.size(); }
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Too backlogged: queue time " + queueTime + " and the size is " + size try {
_log.warn("Too backlogged: queue time " + queueTime + " and the size is " + size
+ ", wantsWrite? " + (0 != (_conKey.interestOps()&SelectionKey.OP_WRITE)) + ", wantsWrite? " + (0 != (_conKey.interestOps()&SelectionKey.OP_WRITE))
+ ", currentOut set? " + currentOutboundSet + ", currentOut set? " + currentOutboundSet
+ ", writeBufs: " + writeBufs + " on " + toString()); + ", writeBufs: " + writeBufs + " on " + toString());
} catch (Exception e) {} // java.nio.channels.CancelledKeyException
_context.statManager().addRateData("ntcp.sendBacklogTime", queueTime, size); _context.statManager().addRateData("ntcp.sendBacklogTime", queueTime, size);
return true; return true;
//} else if (size > 32) { // another arbitrary limit. //} else if (size > 32) { // another arbitrary limit.