I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 7e71ead3 authored by zzz's avatar zzz
Browse files

* Connection limits / throttle:

      - Better limits when no inbound TCP
        (limit inbound and outbound separately)
    * GeoIP:
      - Check netDb SSU IP too
      - Check whole netDb at startup
parent 7feb97e4
No related branches found
No related tags found
No related merge requests found
...@@ -34,7 +34,8 @@ public abstract class CommSystemFacade implements Service { ...@@ -34,7 +34,8 @@ public abstract class CommSystemFacade implements Service {
public int countActivePeers() { return 0; } public int countActivePeers() { return 0; }
public int countActiveSendPeers() { return 0; } public int countActiveSendPeers() { return 0; }
public boolean haveCapacity() { return true; } public boolean haveInboundCapacity() { return true; }
public boolean haveOutboundCapacity() { return true; }
public List getMostRecentErrorMessages() { return Collections.EMPTY_LIST; } public List getMostRecentErrorMessages() { return Collections.EMPTY_LIST; }
/** /**
......
...@@ -13,6 +13,7 @@ import java.io.Writer; ...@@ -13,6 +13,7 @@ import java.io.Writer;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
...@@ -21,6 +22,7 @@ import java.util.Vector; ...@@ -21,6 +22,7 @@ import java.util.Vector;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.data.RouterAddress; import net.i2p.data.RouterAddress;
import net.i2p.data.RouterInfo;
import net.i2p.router.CommSystemFacade; import net.i2p.router.CommSystemFacade;
import net.i2p.router.OutNetMessage; import net.i2p.router.OutNetMessage;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
...@@ -68,7 +70,9 @@ public class CommSystemFacadeImpl extends CommSystemFacade { ...@@ -68,7 +70,9 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
@Override @Override
public int countActiveSendPeers() { return (_manager == null ? 0 : _manager.countActiveSendPeers()); } public int countActiveSendPeers() { return (_manager == null ? 0 : _manager.countActiveSendPeers()); }
@Override @Override
public boolean haveCapacity() { return (_manager == null ? false : _manager.haveCapacity()); } public boolean haveInboundCapacity() { return (_manager == null ? false : _manager.haveInboundCapacity()); }
@Override
public boolean haveOutboundCapacity() { return (_manager == null ? false : _manager.haveOutboundCapacity()); }
/** /**
* Framed average clock skew of connected peers in seconds, or null if we cannot answer. * Framed average clock skew of connected peers in seconds, or null if we cannot answer.
...@@ -352,11 +356,41 @@ public class CommSystemFacadeImpl extends CommSystemFacade { ...@@ -352,11 +356,41 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
return; return;
} }
/*
* GeoIP stuff
*
* This is only used in the router console for now, but we put it here because
* 1) it's a lot easier, and 2) we could use it in the future for peer selection,
* tunnel selection, shitlisting, etc.
*/
/* We hope the routerinfos are read in and things have settled down by now, but it's not required to be so */
private static final int START_DELAY = 5*60*1000; private static final int START_DELAY = 5*60*1000;
private static final int LOOKUP_TIME = 30*60*1000; private static final int LOOKUP_TIME = 30*60*1000;
private void startGeoIP() { private void startGeoIP() {
_geoIP = new GeoIP(_context); _geoIP = new GeoIP(_context);
SimpleScheduler.getInstance().addPeriodicEvent(new Lookup(), START_DELAY, LOOKUP_TIME); SimpleScheduler.getInstance().addEvent(new QueueAll(), START_DELAY);
}
/**
* Collect the IPs for all routers in the DB, and queue them for lookup,
* then fire off the periodic lookup task for the first time.
*
* We could use getAllRouters() if it were public, and that would be faster, but
* we only do this once.
*/
private class QueueAll implements SimpleTimer.TimedEvent {
public void timeReached() {
Set routers = _context.netDb().findNearestRouters(_context.routerHash(), _context.netDb().getKnownRouters(), null);
for (Iterator iter = routers.iterator(); iter.hasNext(); ) {
RouterInfo ri = (RouterInfo) iter.next();
String host = getIPString(ri);
if (host == null)
continue;
_geoIP.add(host);
}
SimpleScheduler.getInstance().addPeriodicEvent(new Lookup(), 5000, LOOKUP_TIME);
}
} }
private class Lookup implements SimpleTimer.TimedEvent { private class Lookup implements SimpleTimer.TimedEvent {
...@@ -370,17 +404,35 @@ public class CommSystemFacadeImpl extends CommSystemFacade { ...@@ -370,17 +404,35 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
} }
/** /**
* Right now this only uses the transport IP, * Uses the transport IP first because that lookup is fast,
* which is present only after you've connected to the peer. * then the SSU IP from the netDb.
* We could also check the IP in the netDb entry...
*/ */
public String getCountry(Hash peer) { public String getCountry(Hash peer) {
byte[] ip = TransportImpl.getIP(peer); byte[] ip = TransportImpl.getIP(peer);
if (ip == null) if (ip != null)
return _geoIP.get(ip);
RouterInfo ri = _context.netDb().lookupRouterInfoLocally(peer);
if (ri == null)
return null;
String s = getIPString(ri);
if (s != null)
return _geoIP.get(s);
return null;
}
private String getIPString(RouterInfo ri) {
// use SSU only, it is likely to be an IP not a hostname,
// we don't want to generate a lot of DNS queries at startup
RouterAddress ra = ri.getTargetAddress("SSU");
if (ra == null)
return null;
Properties props = ra.getOptions();
if (props == null)
return null; return null;
return _geoIP.get(ip); return props.getProperty("host");
} }
/** Provide a consistent "look" for displaying router IDs in the console */
public String renderPeerHTML(Hash peer) { public String renderPeerHTML(Hash peer) {
String h = peer.toBase64().substring(0, 4); String h = peer.toBase64().substring(0, 4);
StringBuffer buf = new StringBuffer(128); StringBuffer buf = new StringBuffer(128);
......
...@@ -204,11 +204,10 @@ public class TransportManager implements TransportEventListener { ...@@ -204,11 +204,10 @@ public class TransportManager implements TransportEventListener {
} }
/** /**
* Is at least one transport below its connection limit + some margin * Is at least one transport below its outbound connection limit + some margin
* Use for throttling in the router. * Use for throttling in the router.
* Perhaps we should just use SSU?
*/ */
public boolean haveCapacity() { public boolean haveOutboundCapacity() {
for (int i = 0; i < _transports.size(); i++) { for (int i = 0; i < _transports.size(); i++) {
if (((Transport)_transports.get(i)).haveCapacity()) if (((Transport)_transports.get(i)).haveCapacity())
return true; return true;
...@@ -216,6 +215,18 @@ public class TransportManager implements TransportEventListener { ...@@ -216,6 +215,18 @@ public class TransportManager implements TransportEventListener {
return false; return false;
} }
/**
* Is at least one transport below its inbound connection limit + some margin
* Use for throttling in the router.
*/
public boolean haveInboundCapacity() {
for (int i = 0; i < _transports.size(); i++) {
if (_transports.get(i).getCurrentAddress() != null && _transports.get(i).haveCapacity())
return true;
}
return false;
}
/** /**
* Return our peer clock skews on all transports. * Return our peer clock skews on all transports.
* Vector composed of Long, each element representing a peer skew in seconds. * Vector composed of Long, each element representing a peer skew in seconds.
......
...@@ -509,9 +509,9 @@ class BuildHandler { ...@@ -509,9 +509,9 @@ class BuildHandler {
* approaching our connection limit (i.e. !haveCapacity()), * approaching our connection limit (i.e. !haveCapacity()),
* reject this request. * reject this request.
*/ */
if (response == 0 && (isInGW || isOutEnd) && if (response == 0 &&
(Boolean.valueOf(_context.getProperty(PROP_REJECT_NONPARTICIPANT)).booleanValue() || ((isInGW && ! _context.commSystem().haveInboundCapacity()) ||
! _context.commSystem().haveCapacity())) { (isOutEnd && ! _context.commSystem().haveOutboundCapacity()))) {
_context.throttle().setTunnelStatus("Rejecting tunnels: Connection limit"); _context.throttle().setTunnelStatus("Rejecting tunnels: Connection limit");
response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH; response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment