2005-09-07 BarkerJr
* HTML cleanup for the router console (thanks!) 2005-09-07 jrandom * Lay the foundation for 'client routers' - the ability for peers to opt out of participating in tunnels entirely due to firewall/NAT issues. Individual routers have control over where those peers are used in tunnels - in outbound or inbound, exploratory or client tunnels, or none at all. The defaults with this build are to simply act as before - placing everyone as potential participants in any tunnel. * Another part of the foundation includes the option for netDb participants to refuse to answer queries regarding peers who are marked as unreachable, though this too is disabled by default (meaning the routerInfo is retrievable from the netDb).
This commit is contained in:
@ -2,7 +2,7 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - logs</title>
|
||||
<title>I2P Router Console - config networking</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - config clients</title>
|
||||
<title>I2P Router Console - config logging</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
<jsp:useBean class="net.i2p.router.web.ConfigLoggingHelper" id="logginghelper" scope="request" />
|
||||
|
@ -3,7 +3,7 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - config clients</title>
|
||||
<title>I2P Router Console - config service</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - home</title>
|
||||
<title>I2P Router Console - internals</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - home</title>
|
||||
<title>I2P Router Console - statistics</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
|
17
history.txt
17
history.txt
@ -1,4 +1,19 @@
|
||||
$Id: history.txt,v 1.239 2005/09/04 15:26:42 jrandom Exp $
|
||||
$Id: history.txt,v 1.240 2005/09/05 14:30:09 jrandom Exp $
|
||||
|
||||
2005-09-07 BarkerJr
|
||||
* HTML cleanup for the router console (thanks!)
|
||||
|
||||
2005-09-07 jrandom
|
||||
* Lay the foundation for 'client routers' - the ability for peers to opt
|
||||
out of participating in tunnels entirely due to firewall/NAT issues.
|
||||
Individual routers have control over where those peers are used in
|
||||
tunnels - in outbound or inbound, exploratory or client tunnels, or
|
||||
none at all. The defaults with this build are to simply act as before -
|
||||
placing everyone as potential participants in any tunnel.
|
||||
* Another part of the foundation includes the option for netDb
|
||||
participants to refuse to answer queries regarding peers who are marked
|
||||
as unreachable, though this too is disabled by default (meaning the
|
||||
routerInfo is retrievable from the netDb).
|
||||
|
||||
2005-09-05 jrandom
|
||||
* Expose the HTTP headers to EepGet status listeners
|
||||
|
10
readme.html
10
readme.html
@ -5,13 +5,12 @@ the number of "Active: " peers rise, and you should see some local "destinations
|
||||
listed (if not, <a href="#trouble">see below</a>). Once those are up, you can:</p>
|
||||
<ul>
|
||||
<li><b>chat anonymously</b> - fire up your own IRC client and connect to the
|
||||
server at <b>localhost port 6668</b>. This points at one of three anonymously hosted
|
||||
server at <b>localhost port 6668</b>. This points at one of two anonymously hosted
|
||||
IRC servers, but neither you nor they know where the other is.</li>
|
||||
<li><b>browse "eepsites"</b> - on I2P there are anonymously hosted websites -
|
||||
tell your browser to use the <b>HTTP proxy at localhost port 4444</b>, then
|
||||
browse to an eepsite -
|
||||
<ul>
|
||||
<li><a href="http://duck.i2p/">duck.i2p</a>: duck's eepsite, with links to other active sites</li>
|
||||
<li><a href="http://ugha.i2p/">ugha.i2p</a>: ugha's eepsite, a wiki that anyone can edit, and lots of links</li>
|
||||
<li><a href="http://orion.i2p/">orion.i2p</a>: a site which tracks eepsite uptime and changes</li>
|
||||
<li><a href="http://forum.i2p/">forum.i2p</a>: a secure and anonymous connection to <a href="http://forum.i2p.net/">forum.i2p.net</a></li>
|
||||
@ -21,7 +20,7 @@ listed (if not, <a href="#trouble">see below</a>). Once those are up, you can:<
|
||||
</ul>
|
||||
There are many more eepsites - just follow the links from the ones you see,
|
||||
bookmark your favorites, and visit them often!</li>
|
||||
<li><b>browse the web</b> - there are a pair of HTTP "outproxies" in I2P hooked
|
||||
<li><b>browse the web</b> - there is currently an HTTP "outproxy" in I2P hooked
|
||||
up to your own HTTP proxy on port 4444 - simply set your browser's proxy to
|
||||
use it (as above) and go to any normal URL - your requests will be bounced
|
||||
through the I2P network.</li>
|
||||
@ -64,7 +63,6 @@ hand side of the page will show up to help you when necessary).</p>
|
||||
<p>If you are still having problems, you may want to review the information on the
|
||||
<a href="http://www.i2p.net/">I2P website</a>, post up messages to the
|
||||
<a href="http://forum.i2p.net/">I2P discussion forum</a>, or swing by #i2p or
|
||||
#i2p-chat on IRC at <a href="irc://irc.freenode.net/#i2p">irc.freenode.net</a>, irc.postman.i2p, irc.freshcoffee.i2p or
|
||||
irc.arcturus.i2p (they're all linked together).</p>
|
||||
#i2p-chat on IRC at <a href="irc://irc.freenode.net/#i2p">irc.freenode.net</a>, irc.postman.i2p or irc.freshcoffee.i2p (they're linked together).</p>
|
||||
|
||||
<p><b>As a note, you can change this page by editing the file "docs/readme.html"</b></p>
|
||||
<p><b>As a note, you can change this page by editing the file "docs/readme.html"</b></p>
|
||||
|
@ -10,6 +10,7 @@ package net.i2p.router;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import net.i2p.data.Hash;
|
||||
|
||||
/**
|
||||
* Manage peer references and keep them up to date so that when asked for peers,
|
||||
@ -25,6 +26,10 @@ public interface PeerManagerFacade extends Service {
|
||||
* @return List of Hash objects of the RouterIdentity for matching peers
|
||||
*/
|
||||
public List selectPeers(PeerSelectionCriteria criteria);
|
||||
public List getPeersByCapability(char capability);
|
||||
public void setCapabilities(Hash peer, String caps);
|
||||
public void removeCapabilities(Hash peer);
|
||||
public Hash selectRandomByCapability(char capability);
|
||||
}
|
||||
|
||||
class DummyPeerManagerFacade implements PeerManagerFacade {
|
||||
@ -33,4 +38,8 @@ class DummyPeerManagerFacade implements PeerManagerFacade {
|
||||
public void restart() {}
|
||||
public void renderStatusHTML(Writer out) { }
|
||||
public List selectPeers(PeerSelectionCriteria criteria) { return null; }
|
||||
public List getPeersByCapability(char capability) { return null; }
|
||||
public void setCapabilities(Hash peer, String caps) {}
|
||||
public void removeCapabilities(Hash peer) {}
|
||||
public Hash selectRandomByCapability(char capability) { return null; }
|
||||
}
|
||||
|
@ -294,6 +294,7 @@ public class Router {
|
||||
ri.setAddresses(_context.commSystem().createAddresses());
|
||||
if (FloodfillNetworkDatabaseFacade.floodfillEnabled(_context))
|
||||
ri.addCapability(FloodfillNetworkDatabaseFacade.CAPACITY_FLOODFILL);
|
||||
addReachabilityCapability(ri);
|
||||
SigningPrivateKey key = _context.keyManager().getSigningPrivateKey();
|
||||
if (key == null) {
|
||||
_log.log(Log.CRIT, "Internal error - signing private key not known? wtf");
|
||||
@ -311,7 +312,31 @@ public class Router {
|
||||
_log.log(Log.CRIT, "Internal error - unable to sign our own address?!", dfe);
|
||||
}
|
||||
}
|
||||
|
||||
public static final char CAPABILITY_REACHABLE = 'R';
|
||||
public static final char CAPABILITY_UNREACHABLE = 'U';
|
||||
public static final String PROP_FORCE_UNREACHABLE = "router.forceUnreachable";
|
||||
|
||||
public void addReachabilityCapability(RouterInfo ri) {
|
||||
String forceUnreachable = _context.getProperty(PROP_FORCE_UNREACHABLE);
|
||||
if ( (forceUnreachable != null) && ("true".equalsIgnoreCase(forceUnreachable)) ) {
|
||||
ri.addCapability(CAPABILITY_UNREACHABLE);
|
||||
return;
|
||||
}
|
||||
switch (_context.commSystem().getReachabilityStatus()) {
|
||||
case CommSystemFacade.STATUS_OK:
|
||||
ri.addCapability(CAPABILITY_REACHABLE);
|
||||
break;
|
||||
case CommSystemFacade.STATUS_DIFFERENT:
|
||||
case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
|
||||
ri.addCapability(CAPABILITY_UNREACHABLE);
|
||||
break;
|
||||
case CommSystemFacade.STATUS_UNKNOWN:
|
||||
// no explicit capability
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ugly list of files that we need to kill if we are building a new identity
|
||||
*
|
||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.226 $ $Date: 2005/09/02 14:10:06 $";
|
||||
public final static String ID = "$Revision: 1.227 $ $Date: 2005/09/04 14:15:49 $";
|
||||
public final static String VERSION = "0.6.0.5";
|
||||
public final static long BUILD = 1;
|
||||
public final static long BUILD = 2;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@ -9,6 +9,7 @@ package net.i2p.router.networkdb;
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.data.DataStructure;
|
||||
@ -25,6 +26,7 @@ import net.i2p.data.i2np.TunnelGatewayMessage;
|
||||
import net.i2p.router.Job;
|
||||
import net.i2p.router.JobImpl;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.TunnelInfo;
|
||||
import net.i2p.router.message.SendMessageDirectJob;
|
||||
import net.i2p.util.Log;
|
||||
@ -109,11 +111,19 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
|
||||
} else {
|
||||
RouterInfo info = getContext().netDb().lookupRouterInfoLocally(_message.getSearchKey());
|
||||
if ( (info != null) && (info.isCurrent(EXPIRE_DELAY)) ) {
|
||||
// send that routerInfo to the _message.getFromHash peer
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("We do have key " + _message.getSearchKey().toBase64()
|
||||
+ " locally as a router info. sending to " + fromKey.toBase64());
|
||||
sendData(_message.getSearchKey(), info, fromKey, _message.getReplyTunnel());
|
||||
if (isUnreachable(info) && !publishUnreachable()) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Not answering a query for a netDb peer who isn't reachable");
|
||||
Set us = new HashSet(1);
|
||||
us.add(getContext().router().getRouterInfo());
|
||||
sendClosest(_message.getSearchKey(), us, fromKey, _message.getReplyTunnel());
|
||||
} else {
|
||||
// send that routerInfo to the _message.getFromHash peer
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("We do have key " + _message.getSearchKey().toBase64()
|
||||
+ " locally as a router info. sending to " + fromKey.toBase64());
|
||||
sendData(_message.getSearchKey(), info, fromKey, _message.getReplyTunnel());
|
||||
}
|
||||
} else {
|
||||
// not found locally - return closest peer routerInfo structs
|
||||
Set routerInfoSet = getContext().netDb().findNearestRouters(_message.getSearchKey(),
|
||||
@ -127,6 +137,24 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUnreachable(RouterInfo info) {
|
||||
if (info == null) return true;
|
||||
String cap = info.getCapabilities();
|
||||
if (cap == null) return false;
|
||||
return cap.indexOf(Router.CAPABILITY_REACHABLE) >= 0;
|
||||
}
|
||||
|
||||
public static final String PROP_PUBLISH_UNREACHABLE = "router.publishUnreachableRouters";
|
||||
public static final boolean DEFAULT_PUBLISH_UNREACHABLE = true;
|
||||
|
||||
private boolean publishUnreachable() {
|
||||
String publish = getContext().getProperty(PROP_PUBLISH_UNREACHABLE);
|
||||
if (publish != null)
|
||||
return Boolean.valueOf(publish).booleanValue();
|
||||
else
|
||||
return DEFAULT_PUBLISH_UNREACHABLE;
|
||||
}
|
||||
|
||||
private boolean weAreClosest(Set routerInfoSet) {
|
||||
boolean weAreClosest = false;
|
||||
for (Iterator iter = routerInfoSet.iterator(); iter.hasNext(); ) {
|
||||
|
@ -47,6 +47,7 @@ public class PublishLocalRouterInfoJob extends JobImpl {
|
||||
ri.setAddresses(getContext().commSystem().createAddresses());
|
||||
if (FloodfillNetworkDatabaseFacade.floodfillEnabled(getContext()))
|
||||
ri.addCapability(FloodfillNetworkDatabaseFacade.CAPACITY_FLOODFILL);
|
||||
getContext().router().addReachabilityCapability(ri);
|
||||
SigningPrivateKey key = getContext().keyManager().getSigningPrivateKey();
|
||||
if (key == null) {
|
||||
_log.log(Log.CRIT, "Internal error - signing private key not known? rescheduling publish for 30s");
|
||||
|
@ -48,7 +48,7 @@ class FloodfillStoreJob extends StoreJob {
|
||||
_facade = facade;
|
||||
}
|
||||
|
||||
protected int getParallelization() { return 2; }
|
||||
protected int getParallelization() { return 1; }
|
||||
protected int getRedundancy() { return 1; }
|
||||
|
||||
/**
|
||||
|
@ -688,7 +688,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
_log.info("RouterInfo " + key.toBase64() + " is stored with "
|
||||
+ routerInfo.getOptions().size() + " options on "
|
||||
+ new Date(routerInfo.getPublished()));
|
||||
|
||||
|
||||
_context.peerManager().setCapabilities(key, routerInfo.getCapabilities());
|
||||
_ds.put(key, routerInfo);
|
||||
synchronized (_lastSent) {
|
||||
if (!_lastSent.containsKey(key))
|
||||
@ -721,6 +722,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
return;
|
||||
}
|
||||
|
||||
_context.peerManager().removeCapabilities(dbEntry);
|
||||
boolean removed = _kb.remove(dbEntry);
|
||||
if (removed) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
@ -737,6 +739,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
|
||||
if (o == null) {
|
||||
boolean removed = _kb.remove(dbEntry);
|
||||
_context.peerManager().removeCapabilities(dbEntry);
|
||||
// if we dont know the key, lets make sure it isn't a now-dead peer
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class SearchJob extends JobImpl {
|
||||
private boolean _deferredCleared;
|
||||
private long _startedOn;
|
||||
|
||||
private static final int SEARCH_BREDTH = 10; // 10 peers at a time
|
||||
private static final int SEARCH_BREDTH = 3; // 10 peers at a time
|
||||
private static final int SEARCH_PRIORITY = 400; // large because the search is probably for a real search
|
||||
/** only send the 10 closest "dont tell me about" refs */
|
||||
static final int MAX_CLOSEST = 10;
|
||||
|
@ -10,11 +10,7 @@ package net.i2p.router.peermanager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.router.PeerSelectionCriteria;
|
||||
@ -30,6 +26,8 @@ class PeerManager {
|
||||
private RouterContext _context;
|
||||
private ProfileOrganizer _organizer;
|
||||
private ProfilePersistenceHelper _persistenceHelper;
|
||||
private List _peersByCapability[];
|
||||
private Map _capabilitiesByPeer;
|
||||
|
||||
public PeerManager(RouterContext context) {
|
||||
_context = context;
|
||||
@ -37,6 +35,10 @@ class PeerManager {
|
||||
_persistenceHelper = new ProfilePersistenceHelper(context);
|
||||
_organizer = context.profileOrganizer();
|
||||
_organizer.setUs(context.routerHash());
|
||||
_capabilitiesByPeer = new HashMap(128);
|
||||
_peersByCapability = new List[26];
|
||||
for (int i = 0; i < _peersByCapability.length; i++)
|
||||
_peersByCapability[i] = new ArrayList(64);
|
||||
loadProfiles();
|
||||
_context.jobQueue().addJob(new EvaluateProfilesJob(_context));
|
||||
//_context.jobQueue().addJob(new PersistProfilesJob(_context, this));
|
||||
@ -116,6 +118,86 @@ class PeerManager {
|
||||
return new ArrayList(peers);
|
||||
}
|
||||
|
||||
public void setCapabilities(Hash peer, String caps) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Setting capabilities for " + peer.toBase64() + " to " + caps);
|
||||
if (caps != null) caps = caps.toLowerCase();
|
||||
synchronized (_capabilitiesByPeer) {
|
||||
String oldCaps = null;
|
||||
if (caps != null)
|
||||
oldCaps = (String)_capabilitiesByPeer.put(peer, caps);
|
||||
else
|
||||
oldCaps = (String)_capabilitiesByPeer.remove(peer);
|
||||
|
||||
if (oldCaps != null) {
|
||||
for (int i = 0; i < oldCaps.length(); i++) {
|
||||
char c = oldCaps.charAt(i);
|
||||
if ( (caps == null) || (caps.indexOf(c) < 0) ) {
|
||||
List peers = locked_getPeers(c);
|
||||
if (peers != null)
|
||||
peers.remove(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (caps != null) {
|
||||
for (int i = 0; i < caps.length(); i++) {
|
||||
char c = caps.charAt(i);
|
||||
if ( (oldCaps != null) && (oldCaps.indexOf(c) >= 0) )
|
||||
continue;
|
||||
List peers = locked_getPeers(c);
|
||||
if ( (peers != null) && (!peers.contains(peer)) )
|
||||
peers.add(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List locked_getPeers(char c) {
|
||||
c = Character.toLowerCase(c);
|
||||
int i = c - 'a';
|
||||
if ( (i < 0) || (i >= _peersByCapability.length) ) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Invalid capability " + c + " (" + i + ")");
|
||||
return null;
|
||||
}
|
||||
return _peersByCapability[i];
|
||||
}
|
||||
|
||||
public void removeCapabilities(Hash peer) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Removing capabilities from " + peer.toBase64());
|
||||
synchronized (_capabilitiesByPeer) {
|
||||
String oldCaps = (String)_capabilitiesByPeer.remove(peer);
|
||||
if (oldCaps != null) {
|
||||
for (int i = 0; i < oldCaps.length(); i++) {
|
||||
char c = oldCaps.charAt(i);
|
||||
List peers = locked_getPeers(c);
|
||||
if (peers != null)
|
||||
peers.remove(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public Hash selectRandomByCapability(char capability) {
|
||||
int index = _context.random().nextInt(Integer.MAX_VALUE);
|
||||
synchronized (_capabilitiesByPeer) {
|
||||
List peers = locked_getPeers(capability);
|
||||
if ( (peers != null) && (peers.size() > 0) ) {
|
||||
index = index % peers.size();
|
||||
return (Hash)peers.get(index);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public List getPeersByCapability(char capability) {
|
||||
synchronized (_capabilitiesByPeer) {
|
||||
List peers = locked_getPeers(capability);
|
||||
if (peers != null)
|
||||
return new ArrayList(peers);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void renderStatusHTML(Writer out) throws IOException {
|
||||
_organizer.renderStatusHTML(out);
|
||||
}
|
||||
|
@ -10,8 +10,10 @@ package net.i2p.router.peermanager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.router.PeerManagerFacade;
|
||||
import net.i2p.router.PeerSelectionCriteria;
|
||||
import net.i2p.router.RouterContext;
|
||||
@ -57,8 +59,26 @@ public class PeerManagerFacadeImpl implements PeerManagerFacade {
|
||||
public List selectPeers(PeerSelectionCriteria criteria) {
|
||||
return _manager.selectPeers(criteria);
|
||||
}
|
||||
|
||||
|
||||
public void setCapabilities(Hash peer, String caps) {
|
||||
if (_manager == null) return;
|
||||
_manager.setCapabilities(peer, caps);
|
||||
}
|
||||
public void removeCapabilities(Hash peer) {
|
||||
if (_manager == null) return;
|
||||
_manager.removeCapabilities(peer);
|
||||
}
|
||||
public Hash selectRandomByCapability(char capability) {
|
||||
if (_manager == null) return null;
|
||||
return _manager.selectRandomByCapability(capability);
|
||||
}
|
||||
public List getPeersByCapability(char capability) {
|
||||
if (_manager == null) return new ArrayList(0);
|
||||
return _manager.getPeersByCapability(capability);
|
||||
}
|
||||
|
||||
public void renderStatusHTML(Writer out) throws IOException {
|
||||
_manager.renderStatusHTML(out);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public class CreateRouterInfoJob extends JobImpl {
|
||||
stats.setProperty(RouterInfo.PROP_NETWORK_ID, Router.NETWORK_ID+"");
|
||||
if (FloodfillNetworkDatabaseFacade.floodfillEnabled(getContext()))
|
||||
info.addCapability(FloodfillNetworkDatabaseFacade.CAPACITY_FLOODFILL);
|
||||
getContext().router().addReachabilityCapability(info);
|
||||
info.setOptions(stats);
|
||||
info.setPeers(new HashSet());
|
||||
info.setPublished(getCurrentPublishDate(getContext()));
|
||||
|
@ -129,6 +129,7 @@ public class RebuildRouterInfoJob extends JobImpl {
|
||||
info.setOptions(stats);
|
||||
if (FloodfillNetworkDatabaseFacade.floodfillEnabled(getContext()))
|
||||
info.addCapability(FloodfillNetworkDatabaseFacade.CAPACITY_FLOODFILL);
|
||||
getContext().router().addReachabilityCapability(info);
|
||||
// info.setPeers(new HashSet()); // this would have the trusted peers
|
||||
info.setPublished(CreateRouterInfoJob.getCurrentPublishDate(getContext()));
|
||||
|
||||
|
@ -75,7 +75,10 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
||||
return _manager.getMostRecentErrorMessages();
|
||||
}
|
||||
|
||||
public short getReachabilityStatus() { return _manager.getReachabilityStatus(); }
|
||||
public short getReachabilityStatus() {
|
||||
if (_manager == null) return CommSystemFacade.STATUS_UNKNOWN;
|
||||
return _manager.getReachabilityStatus();
|
||||
}
|
||||
public void recheckReachability() { _manager.recheckReachability(); }
|
||||
|
||||
public void renderStatusHTML(Writer out) throws IOException {
|
||||
|
@ -9,14 +9,7 @@ import java.io.Writer;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataHelper;
|
||||
@ -250,7 +243,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
_refiller.startup();
|
||||
_flooder.startup();
|
||||
_expireEvent.setIsAlive(true);
|
||||
_testEvent.setIsAlive(true);
|
||||
_testEvent.setIsAlive(true); // this queues it for 3-6 minutes in the future...
|
||||
SimpleTimer.getInstance().addEvent(_testEvent, 10*1000); // lets requeue it for Real Soon
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
@ -832,19 +826,33 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
return active;
|
||||
}
|
||||
|
||||
private static class AlphaComparator implements Comparator {
|
||||
private static final AlphaComparator _instance = new AlphaComparator();
|
||||
public static final AlphaComparator instance() { return _instance; }
|
||||
|
||||
public int compare(Object lhs, Object rhs) {
|
||||
if ( (lhs == null) || (rhs == null) || !(lhs instanceof PeerState) || !(rhs instanceof PeerState))
|
||||
throw new IllegalArgumentException("rhs = " + rhs + " lhs = " + lhs);
|
||||
PeerState l = (PeerState)lhs;
|
||||
PeerState r = (PeerState)rhs;
|
||||
// base64 retains binary ordering
|
||||
return DataHelper.compareTo(l.getRemotePeer().getData(), r.getRemotePeer().getData());
|
||||
}
|
||||
|
||||
}
|
||||
public void renderStatusHTML(Writer out) throws IOException {
|
||||
List peers = null;
|
||||
TreeSet peers = new TreeSet(AlphaComparator.instance());
|
||||
synchronized (_peersByIdent) {
|
||||
peers = new ArrayList(_peersByIdent.values());
|
||||
peers.addAll(_peersByIdent.values());
|
||||
}
|
||||
long offsetTotal = 0;
|
||||
|
||||
StringBuffer buf = new StringBuffer(512);
|
||||
buf.append("<b>UDP connections: ").append(peers.size()).append("</b><br />\n");
|
||||
buf.append("<table border=\"1\">\n");
|
||||
buf.append(" <tr><td><b>peer</b></td><td><b>activity (in/out)</b></td>");
|
||||
buf.append(" <td><b>transfer (in/out)</b></td>\n");
|
||||
buf.append(" <td><b>uptime</b></td><td><b>skew</b></td>\n");
|
||||
buf.append(" <tr><td><b>peer</b></td><td><b>idle</b></td>");
|
||||
buf.append(" <td><b>in/out</b></td>\n");
|
||||
buf.append(" <td><b>up</b></td><td><b>skew</b></td>\n");
|
||||
buf.append(" <td><b>cwnd</b></td><td><b>ssthresh</b></td>\n");
|
||||
buf.append(" <td><b>rtt</b></td><td><b>dev</b></td><td><b>rto</b></td>\n");
|
||||
buf.append(" <td><b>send</b></td><td><b>recv</b></td>\n");
|
||||
@ -853,42 +861,67 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
long now = _context.clock().now();
|
||||
for (int i = 0; i < peers.size(); i++) {
|
||||
PeerState peer = (PeerState)peers.get(i);
|
||||
for (Iterator iter = peers.iterator(); iter.hasNext(); ) {
|
||||
PeerState peer = (PeerState)iter.next();
|
||||
if (now-peer.getLastReceiveTime() > 60*60*1000)
|
||||
continue; // don't include old peers
|
||||
|
||||
buf.append("<tr>");
|
||||
|
||||
String name = peer.getRemotePeer().toBase64().substring(0,6);
|
||||
buf.append("<td nowrap>");
|
||||
buf.append("<td valign=\"top\" nowrap><code>");
|
||||
buf.append("<a href=\"netdb.jsp#");
|
||||
buf.append(name);
|
||||
buf.append("\">");
|
||||
buf.append(name).append("@");
|
||||
byte ip[] = peer.getRemoteIP();
|
||||
for (int j = 0; j < ip.length; j++) {
|
||||
buf.append(ip[j] & 0xFF);
|
||||
int num = ip[j] & 0xFF;
|
||||
if (num < 10)
|
||||
buf.append("00");
|
||||
else if (num < 100)
|
||||
buf.append("0");
|
||||
buf.append(num);
|
||||
if (j + 1 < ip.length)
|
||||
buf.append('.');
|
||||
}
|
||||
buf.append(':').append(peer.getRemotePort());
|
||||
buf.append(':');
|
||||
int port = peer.getRemotePort();
|
||||
if (port < 10)
|
||||
buf.append("0000");
|
||||
else if (port < 100)
|
||||
buf.append("000");
|
||||
else if (port < 1000)
|
||||
buf.append("00");
|
||||
else if (port < 10000)
|
||||
buf.append("0");
|
||||
buf.append(port);
|
||||
buf.append("</a>");
|
||||
if (_activeThrottle.isChoked(peer.getRemotePeer()))
|
||||
boolean appended = false;
|
||||
if (_activeThrottle.isChoked(peer.getRemotePeer())) {
|
||||
if (!appended) buf.append("<br />");
|
||||
buf.append(" [choked]");
|
||||
if (peer.getConsecutiveFailedSends() > 0)
|
||||
appended = true;
|
||||
}
|
||||
if (peer.getConsecutiveFailedSends() > 0) {
|
||||
if (!appended) buf.append("<br />");
|
||||
buf.append(" [").append(peer.getConsecutiveFailedSends()).append(" failures]");
|
||||
if (_context.shitlist().isShitlisted(peer.getRemotePeer()))
|
||||
appended = true;
|
||||
}
|
||||
if (_context.shitlist().isShitlisted(peer.getRemotePeer())) {
|
||||
if (!appended) buf.append("<br />");
|
||||
buf.append(" [shitlisted]");
|
||||
buf.append("</td>");
|
||||
appended = true;
|
||||
}
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append((now-peer.getLastReceiveTime())/1000);
|
||||
buf.append("s/");
|
||||
buf.append((now-peer.getLastSendTime())/1000);
|
||||
buf.append("s</td>");
|
||||
buf.append("s</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(formatKBps(peer.getReceiveBps()));
|
||||
buf.append("KBps/");
|
||||
buf.append(formatKBps(peer.getSendBps()));
|
||||
@ -897,60 +930,60 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
//buf.append("KBps/");
|
||||
//buf.append(formatKBps(peer.getSendACKBps()));
|
||||
//buf.append("KBps ");
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(DataHelper.formatDuration(now-peer.getKeyEstablishedTime()));
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getClockSkew()/1000);
|
||||
buf.append("s</td>");
|
||||
buf.append("s</code></td>");
|
||||
offsetTotal = offsetTotal + peer.getClockSkew();
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getSendWindowBytes()/1024);
|
||||
buf.append("K</td>");
|
||||
buf.append("K</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getSlowStartThreshold()/1024);
|
||||
buf.append("K</td>");
|
||||
buf.append("K</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getRTT());
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getRTTDeviation());
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getRTO());
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getPacketsTransmitted());
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(peer.getPacketsReceived());
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
double sent = (double)peer.getPacketsPeriodTransmitted();
|
||||
double sendLostPct = 0;
|
||||
if (sent > 0)
|
||||
sendLostPct = (double)peer.getPacketsRetransmitted()/(sent);
|
||||
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
//buf.append(formatPct(sendLostPct));
|
||||
buf.append(peer.getPacketsRetransmitted()); // + "/" + peer.getPacketsPeriodRetransmitted() + "/" + sent);
|
||||
//buf.append(peer.getPacketRetransmissionRate());
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
double recvDupPct = (double)peer.getPacketsReceivedDuplicate()/(double)peer.getPacketsReceived();
|
||||
buf.append("<td>");
|
||||
buf.append("<td valign=\"top\" ><code>");
|
||||
buf.append(formatPct(recvDupPct));
|
||||
buf.append("</td>");
|
||||
buf.append("</code></td>");
|
||||
|
||||
buf.append("</tr>");
|
||||
out.write(buf.toString());
|
||||
|
@ -1,9 +1,6 @@
|
||||
package net.i2p.router.tunnel.pool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
|
||||
@ -22,7 +19,8 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
if (shouldSelectExplicit(settings))
|
||||
return selectExplicit(ctx, settings, length);
|
||||
|
||||
ctx.profileOrganizer().selectFastPeers(length, null, matches);
|
||||
Set exclude = getExclude(ctx, settings.isInbound(), settings.isExploratory());
|
||||
ctx.profileOrganizer().selectFastPeers(length, exclude, matches);
|
||||
|
||||
matches.remove(ctx.routerHash());
|
||||
ArrayList rv = new ArrayList(matches);
|
||||
|
@ -1,9 +1,6 @@
|
||||
package net.i2p.router.tunnel.pool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
import net.i2p.util.Log;
|
||||
@ -30,7 +27,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
return rv;
|
||||
}
|
||||
|
||||
HashSet exclude = new HashSet(1);
|
||||
Set exclude = getExclude(ctx, settings.isInbound(), settings.isExploratory());
|
||||
exclude.add(ctx.routerHash());
|
||||
HashSet matches = new HashSet(length);
|
||||
ctx.profileOrganizer().selectNotFailingPeers(length, exclude, matches, false);
|
||||
|
@ -1,12 +1,9 @@
|
||||
package net.i2p.router.tunnel.pool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.*;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
import net.i2p.util.Log;
|
||||
@ -114,4 +111,47 @@ abstract class TunnelPeerSelector {
|
||||
log.info(toString() + ": Selecting peers explicitly: " + rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick peers that we want to avoid
|
||||
*/
|
||||
public Set getExclude(RouterContext ctx, boolean isInbound, boolean 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 {
|
||||
return new HashSet(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "router.outboundExploratoryExcludeUnreachable";
|
||||
private static final String PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = "router.outboundClientExcludeUnreachable";
|
||||
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;
|
||||
|
||||
protected boolean filterUnreachable(RouterContext ctx, boolean isInbound, boolean isExploratory) {
|
||||
boolean def = false;
|
||||
String val = null;
|
||||
|
||||
if (isExploratory)
|
||||
if (isInbound)
|
||||
val = ctx.getProperty(PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE);
|
||||
else
|
||||
val = ctx.getProperty(PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE);
|
||||
else
|
||||
if (isInbound)
|
||||
val = ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE);
|
||||
else
|
||||
val = ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE);
|
||||
|
||||
boolean rv = (val != null ? Boolean.valueOf(val).booleanValue() : def);
|
||||
//System.err.println("Filter unreachable? " + rv + " (inbound? " + isInbound + ", exploratory? " + isExploratory);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user