2007-09-22 zzz
* Send messages for the same destination out the same outbound tunnel to reduce out-of-order delivery.
This commit is contained in:
@ -1,4 +1,8 @@
|
||||
$Id: history.txt,v 1.588 2007-09-18 14:09:21 zzz Exp $
|
||||
$Id: history.txt,v 1.589 2007-09-19 20:44:05 zzz Exp $
|
||||
|
||||
2007-09-22 zzz
|
||||
* Send messages for the same destination out the same outbound
|
||||
tunnel to reduce out-of-order delivery.
|
||||
|
||||
2007-09-19 zzz
|
||||
* i2psnark: Fix broken multifile torrent Delete;
|
||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.524 $ $Date: 2007-09-18 14:09:19 $";
|
||||
public final static String ID = "$Revision: 1.525 $ $Date: 2007-09-19 20:44:02 $";
|
||||
public final static String VERSION = "0.6.1.29";
|
||||
public final static long BUILD = 6;
|
||||
public final static long BUILD = 7;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@ -41,6 +41,9 @@ public interface TunnelManagerFacade extends Service {
|
||||
*
|
||||
*/
|
||||
boolean isInUse(Hash peer);
|
||||
|
||||
/** Is a tunnel a valid member of the pool? */
|
||||
public boolean isValidTunnel(Hash client, TunnelInfo tunnel);
|
||||
|
||||
/** how many tunnels are we participating in? */
|
||||
public int getParticipatingCount();
|
||||
@ -85,6 +88,7 @@ class DummyTunnelManagerFacade implements TunnelManagerFacade {
|
||||
public TunnelInfo selectOutboundTunnel() { return null; }
|
||||
public TunnelInfo selectOutboundTunnel(Hash destination) { return null; }
|
||||
public boolean isInUse(Hash peer) { return false; }
|
||||
public boolean isValidTunnel(Hash client, TunnelInfo tunnel) { return false; }
|
||||
public int getParticipatingCount() { return 0; }
|
||||
public int getFreeTunnelCount() { return 0; }
|
||||
public int getOutboundTunnelCount() { return 0; }
|
||||
|
@ -2,6 +2,7 @@ package net.i2p.router.message;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -378,7 +379,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
||||
+ _lease.getTunnelId() + " on "
|
||||
+ _lease.getGateway().toBase64());
|
||||
|
||||
_outTunnel = selectOutboundTunnel();
|
||||
_outTunnel = selectOutboundTunnel(_to);
|
||||
if (_outTunnel != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(getJobId() + ": Sending tunnel message out " + _outTunnel.getSendTunnelId(0) + " to "
|
||||
@ -434,6 +435,45 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use the same outbound tunnel as we did for the same destination previously,
|
||||
* if possible, to keep the streaming lib happy
|
||||
*
|
||||
*/
|
||||
private static HashMap _tunnelCache = new HashMap();
|
||||
private static long _cleanTime = 0;
|
||||
private TunnelInfo selectOutboundTunnel(Destination to) {
|
||||
TunnelInfo tunnel;
|
||||
long now = getContext().clock().now();
|
||||
synchronized (_tunnelCache) {
|
||||
if (now - _cleanTime > 5*60*1000) { // clean out periodically
|
||||
List deleteList = new ArrayList();
|
||||
for (Iterator iter = _tunnelCache.keySet().iterator(); iter.hasNext(); ) {
|
||||
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;
|
||||
}
|
||||
tunnel = (TunnelInfo) _tunnelCache.get(to);
|
||||
if (tunnel != null) {
|
||||
if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel))
|
||||
return(tunnel);
|
||||
else
|
||||
_tunnelCache.remove(to);
|
||||
}
|
||||
tunnel = selectOutboundTunnel();
|
||||
if (tunnel != null)
|
||||
_tunnelCache.put(to, tunnel);
|
||||
}
|
||||
return tunnel;
|
||||
}
|
||||
/**
|
||||
* Pick an arbitrary outbound tunnel to send the message through, or null if
|
||||
* there aren't any around
|
||||
|
@ -187,6 +187,19 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isValidTunnel(Hash client, TunnelInfo tunnel) {
|
||||
if (tunnel.getExpiration() < _context.clock().now())
|
||||
return false;
|
||||
TunnelPool pool;
|
||||
if (tunnel.isInbound())
|
||||
pool = (TunnelPool)_clientInboundPools.get(client);
|
||||
else
|
||||
pool = (TunnelPool)_clientOutboundPools.get(client);
|
||||
if (pool == null)
|
||||
return false;
|
||||
return pool.listTunnels().contains(tunnel);
|
||||
}
|
||||
|
||||
public TunnelPoolSettings getInboundSettings() { return _inboundExploratory.getSettings(); }
|
||||
public TunnelPoolSettings getOutboundSettings() { return _outboundExploratory.getSettings(); }
|
||||
public void setInboundSettings(TunnelPoolSettings settings) { _inboundExploratory.setSettings(settings); }
|
||||
@ -498,7 +511,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
||||
String cap = getCapacity(peer);
|
||||
TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
|
||||
if (_context.routerHash().equals(peer))
|
||||
out.write("<td><i>" + peer.toBase64().substring(0,4) + (id == null ? "" : ":" + id) + "</i>" + cap + "</td>");
|
||||
out.write("<td>" + (id == null ? "" : "" + id) + "</td>");
|
||||
else
|
||||
out.write("<td>" + peer.toBase64().substring(0,4) + (id == null ? "" : ":" + id) + cap + "</td>");
|
||||
}
|
||||
|
Reference in New Issue
Block a user