merge of '80aa8cd653ef7ee96cd6603b9646c53b2ff84760'

and 'da25b770e65a36f3056b905cc6b96be431076a6b'
This commit is contained in:
dev
2013-06-13 15:05:54 +00:00
3 changed files with 157 additions and 216 deletions

View File

@ -1,11 +1,18 @@
package net.i2p.router; package net.i2p.router;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.Properties; import java.util.Properties;
import java.util.Scanner;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.data.RouterInfo;
import net.i2p.router.Router;
import net.i2p.util.Log; import net.i2p.util.Log;
/** /**
@ -16,7 +23,7 @@ import net.i2p.util.Log;
* contained in them are used for the context's getProperty(name)). <p /> * contained in them are used for the context's getProperty(name)). <p />
* *
* <b>Usage:</b><pre> * <b>Usage:</b><pre>
* MultiRouter globalContextFile routerContextFile[ routerContextFile]* * MultiRouter numberRouters
* </pre> * </pre>
* *
* Each routerContext specified is used to boot up a single router. It is HIGHLY * Each routerContext specified is used to boot up a single router. It is HIGHLY
@ -36,72 +43,181 @@ import net.i2p.util.Log;
* that need the encryption enabled). To run a client app through a router that * that need the encryption enabled). To run a client app through a router that
* has i2p.encryption=off, you should also add that line to the client's JVM * has i2p.encryption=off, you should also add that line to the client's JVM
* (for example, <code>java -Di2p.encryption=off -jar lib/i2ptunnel.jar</code>).<p /> * (for example, <code>java -Di2p.encryption=off -jar lib/i2ptunnel.jar</code>).<p />
*
* To make the router console work, either run from a directory containing
* lib/, webapps/, docs/, etc., or point i2p.dir.base to a directory containing the
* above.
* *
* The multirouter waits until all of the routers are shut down (which none will * The multirouter waits until all of the routers are shut down (which none will
* do on their own, so as before, you'll want to kill the proc or ^C it). * do on their own, so as before, you'll want to kill the proc or ^C it).
*/ */
public class MultiRouter { public class MultiRouter {
private static Log _log;
private static ArrayList _routers = new ArrayList(8); private static final int BASE_PORT = 5000;
private static int nbrRouters;
private static PrintStream _out;
private static ArrayList<Router> _routers = new ArrayList<Router>(8);
private static I2PAppContext _defaultContext; private static I2PAppContext _defaultContext;
public static void main(String args[]) { public static void main(String args[]) {
if ( (args == null) || (args.length <= 1) ) { if ( (args == null) || (args.length < 1) ) {
usage();
return;
}
Scanner scan = new Scanner(args[0]);
if (!scan.hasNextInt()) {
usage();
return;
}
nbrRouters = scan.nextInt();
if (nbrRouters < 0) {
usage(); usage();
return; return;
} }
_defaultContext = new I2PAppContext(getEnv(args[0]));
_log = _defaultContext.logManager().getLog(MultiRouter.class);
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
_out = System.out;
buildClientProps(0);
_defaultContext = new I2PAppContext(buildRouterProps(0));
_defaultContext.clock().setOffset(0); _defaultContext.clock().setOffset(0);
Runtime.getRuntime().addShutdownHook(new Thread() { Runtime.getRuntime().addShutdownHook(new Thread() {
@Override @Override
public void run() { public void run() {
Thread.currentThread().setName("Router* Shutdown"); _out.println("Shutting down in a few moments..");
try { Thread.sleep(120*1000); } catch (InterruptedException ie) {} for(Router r : _routers) {
Runtime.getRuntime().halt(-1); r.shutdown(-1);
}
try { Thread.sleep(1500); } catch (InterruptedException ie) {}
Runtime.getRuntime().halt(0);
} }
}); });
for (int i = 1; i < args.length; i++) { for (int i = 0; i < nbrRouters; i++) {
Router router = new Router(getEnv(args[i])); Router router = new Router(buildRouterProps(i));
router.setKillVMOnEnd(false); router.setKillVMOnEnd(false);
_routers.add(router); _routers.add(router);
_log.info("Router " + i + " created from " + args[i]); _out.println("Router " + i + " was created");
//try { Thread.sleep(2*1000); } catch (InterruptedException ie) {}
} }
for (int i = 0; i < _routers.size(); i++) { for (int i = 0; i < nbrRouters; i++) {
Router r = (Router)_routers.get(i); Router r = _routers.get(i);
long offset = r.getContext().random().nextLong(Router.CLOCK_FUDGE_FACTOR/2); long offset = r.getContext().random().nextLong(Router.CLOCK_FUDGE_FACTOR/2);
if (r.getContext().random().nextBoolean()) if (r.getContext().random().nextBoolean())
offset = 0 - offset; offset = 0 - offset;
r.getContext().clock().setOffset(offset, true); r.getContext().clock().setOffset(offset, true);
r.runRouter(); r.runRouter();
_log.info("Router " + i + " started with clock offset " + offset); _out.println("Router " + i + " was started with time offset " + offset);
try { Thread.sleep(2*1000 + new java.util.Random().nextInt(2)*1000); } catch (InterruptedException ie) {}
} }
_log.info("All " + _routers.size() + " routers started up"); _out.println("All routers have been started");
/* Wait for routers to start services and generate keys.. */
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
internalReseed();
waitForCompletion(); waitForCompletion();
} }
private static Properties getEnv(String filename) { private static void internalReseed() {
Properties props = new Properties();
FileInputStream in = null; HashSet<RouterInfo> riSet = new HashSet<RouterInfo>();
try { for(Router r : _routers) {
in = new FileInputStream(filename); riSet.addAll(r.getContext().netDb().getRouters());
props.load(in); }
props.setProperty("time.disabled", "true"); for(Router r : _routers) {
return props; for(RouterInfo ri : riSet){
} catch (IOException ioe) { r.getContext().netDb().publish(ri);
ioe.printStackTrace(); }
return null; }
} finally { _out.println(riSet.size() + " RouterInfos were reseeded");
if (in != null) try { in.close(); } catch (IOException ioe) {} }
private static Properties buildRouterProps(int id) {
Properties props = getRouterProps(id);
File f = new File(props.getProperty("router.configLocation"));
f.getParentFile().mkdirs();
if (!f.exists()) {
try {
DataHelper.storeProps(props, f);
} catch (IOException e) {
e.printStackTrace();
}
} }
return props;
}
private static Properties getRouterProps(int id) {
Properties props = new Properties();
props.setProperty("router.profileDir", "/peerProfiles");
props.setProperty("router.sessionKeys.location", "/sessionKeys.dat");
props.setProperty("router.info.location", "/router.info");
props.setProperty("router.keys.location", "/router.keys");
props.setProperty("router.networkDatabase.dbDir", "/netDb");
props.setProperty("router.tunnelPoolFile", "/tunnelPool.dat");
props.setProperty("router.keyBackupDir", "/keyBackup");
props.setProperty("router.clientConfigFile", getBaseDir(id) + "/clients.config");
props.setProperty("router.configLocation", getBaseDir(id) + "/router.config");
props.setProperty("router.pingFile", getBaseDir(id) + "/router.ping");
props.setProperty("router.rejectStartupTime", "0");
props.setProperty("router.reseedDisable", "true");
props.setProperty("i2p.dir.app", getBaseDir(id));
/* If MultiRouter is not run from a dir containing lib/, webapps/, docs/, etc.
* point i2p.dir.base to a directory containing the above. */
//props.setProperty("i2p.dir.base", getBaseDir(id));
props.setProperty("i2p.dir.config", getBaseDir(id));
props.setProperty("i2p.dir.log", getBaseDir(id));
props.setProperty("i2p.dir.router", getBaseDir(id));
props.setProperty("i2p.dir.pid", getBaseDir(id));
//props.setProperty("i2p.vmCommSystem", "true");
props.setProperty("i2np.ntcp.hostname", "127.0.0.1");
props.setProperty("i2np.udp.host", "127.0.0.1");
props.setProperty("i2np.ntcp.port", BASE_PORT + id + "");
props.setProperty("i2np.udp.port", BASE_PORT + id + "");
props.setProperty("i2np.ntcp.allowLocal", "true");
props.setProperty("i2np.udp.allowLocal", "true");
props.setProperty("i2np.udp.internalPort", BASE_PORT + id + "");
props.setProperty("i2cp.port", Integer.toString((BASE_PORT + nbrRouters + id)));
return props;
}
private static Properties buildClientProps(int id) {
Properties rProps = getRouterProps(id);
Properties props = getClientProps();
File f = new File(rProps.getProperty("router.clientConfigFile"));
f.getParentFile().mkdirs();
if (!f.exists()) {
try {
DataHelper.storeProps(props, f);
} catch (IOException e) {
e.printStackTrace();
}
}
return props;
}
private static Properties getClientProps() {
Properties props = new Properties();
props.setProperty("clientApp.0.args", (BASE_PORT-1) + " 127.0.0.1 ./webapps");
props.setProperty("clientApp.0.main", "net.i2p.router.web.RouterConsoleRunner");
props.setProperty("clientApp.0.name", "webconsole");
props.setProperty("clientApp.0.onBoot", "true");
props.setProperty("clientApp.1.args", "i2ptunnel.config");
props.setProperty("clientApp.1.main", "net.i2p.i2ptunnel.TunnelControllerGroup");
props.setProperty("clientApp.1.name", "tunnels");
props.setProperty("clientApp.1.delay", "6");
return props;
}
private static String getBaseDir(int id) {
File f = new File(".");
return f.getAbsoluteFile().getParentFile().toString() + "/multirouter/"+ Integer.toString(id);
} }
private static void waitForCompletion() { private static void waitForCompletion() {
@ -110,8 +226,7 @@ public class MultiRouter {
for (int i = 0; i < _routers.size(); i++) { for (int i = 0; i < _routers.size(); i++) {
Router r = (Router)_routers.get(i); Router r = (Router)_routers.get(i);
if (!r.isAlive()) { if (!r.isAlive()) {
if (_log.shouldLog(Log.INFO)) _out.println("Router " + i + " is dead");
_log.info("Router " + i + " is dead");
} else { } else {
alive++; alive++;
} }
@ -122,13 +237,11 @@ public class MultiRouter {
break; break;
} }
} }
_log.info("All routers shut down"); _out.println("All routers shut down");
} }
private static void usage() { private static void usage() {
System.err.println("Usage: MultiRouter globalContextFile routerContextFile[ routerContextFile]*"); System.err.println("Usage: MultiRouter nbr_routers");
System.err.println(" The context files contain key=value entries specifying properties"); System.err.println(" Where nbr_routers > 0");
System.err.println(" to load into the given context. In addition, each routerContextFile");
System.err.println(" in turn is used to boot a router");
} }
} }

View File

@ -1,173 +0,0 @@
package net.i2p.router;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Build a set of config files suitable for use by the multirouter as a
* simulation, as well as a pair of scripts for running the simulation.
* Usage: <pre>
* MultiRouterBuilder [routerDir routerPortStart]*
* </pre>
*
* Each router is configured with their own $routerDir/router.config file so
* that all of its data is stored under the $routerDir (profiles, keys, netDb,
* etc). In addition, each router has the i2cp port set to $routerPortStart+1,
* the admin port set to $routerPortStart+2, and some commented out clientApp
* lines (configured with the SAM bridge at $routerPortStart+3 and an EepProxy at
* $routerPortStart+4).<p />
*
* It then builds a $routerDir/heartbeat.config containing the following lines:<ul>
* <li>i2cpHost=localhost</li>
* <li>i2cpPort=$routerPortStart+1</li>
* <li>numHops=2</li>
* <li>privateDestinationFile=$routerDir/heartbeat.keys</li>
* <li>publicDestinationFile=$routerDir/heartbeat.txt</li>
* </ul>
*
* Then it goes on to create the $routerDir/routerEnv.txt:<ul>
* <li>loggerFilenameOverride=$routerDir/logs/log-router-#.txt</li>
* <li>router.configLocation=$routerDir/router.config</li>
* <li>i2p.vmCommSystem=true</li>
* <li>i2p.encryption=off</li>
* </ul>
*
* In addition, it creates a baseEnv.txt: <ul>
* <li>loggerFilenameOverride=logs/log-base-#.txt</li>
* </ul>
*
* Finally, it creates the MultiRouter startup script to launch all of these
* routers, stored at runNetSim.bat / runNetSim.sh
*
*/
public class MultiRouterBuilder {
public static void main(String args[]) {
if (args.length < 2) {
usage();
return;
}
for (int i = 0; i < args.length; i += 2) {
String dir = args[i];
try {
int basePortNum = Integer.parseInt(args[i+1]);
buildConfig(dir, basePortNum, i == 0);
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
}
buildBaseEnv();
buildStartupScript(args);
}
private static void buildBaseEnv() {
File envFile = new File("baseEnv.txt");
try {
FileOutputStream fos = new FileOutputStream(envFile);
fos.write(("loggerFilenameOverride=logs/log-base-#.txt\n").getBytes());
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
File f = new File("logs");
f.mkdirs();
}
private static void buildStartupScript(String args[]) {
buildStartupScriptNix(args);
}
private static void buildStartupScriptNix(String args[]) {
StringBuilder buf = new StringBuilder(4096);
buf.append("#!/bin/sh\n");
buf.append("export CP=.; for LIB in lib/* ; do export CP=$CP:$LIB ; done\n");
buf.append("nohup java -cp $CP ");
buf.append(" -Xmx1024m");
buf.append(" -Djava.library.path=.");
buf.append(" -DloggerFilenameOverride=logs/log-sim-#.txt");
buf.append(" -Dorg.mortbay.http.Version.paranoid=true");
buf.append(" -Dorg.mortbay.util.FileResource.checkAliases=false");
buf.append(" -verbose:gc");
buf.append(" net.i2p.router.MultiRouter baseEnv.txt ");
for (int i = 0; i < args.length; i += 2)
buf.append(args[i]).append("/routerEnv.txt ");
buf.append(" > sim.out 2>&1 &\n");
buf.append("echo $! > sim.pid\n");
buf.append("echo \"After all of the routers have started up, you should cross seed them\"\n");
buf.append("echo \"Simply copy */netDb/routerInfo-* to all of the various */netDb/ directories\"\n");
try {
FileOutputStream fos = new FileOutputStream("runNetSim.sh");
fos.write(buf.toString().getBytes());
fos.close();
} catch (IOException ioe) { ioe.printStackTrace(); }
}
private static void buildConfig(String dir, int basePort, boolean isFirst) {
File baseDir = new File(dir);
baseDir.mkdirs();
File cfgFile = new File(baseDir, "router.config");
StringBuilder buf = new StringBuilder(8*1024);
buf.append("router.profileDir=").append(baseDir.getPath()).append("/peerProfiles\n");
buf.append("router.historyFilename=").append(baseDir.getPath()).append("/messageHistory.txt\n");
buf.append("router.sessionKeys.location=").append(baseDir.getPath()).append("/sessionKeys.dat\n");
buf.append("router.info.location=").append(baseDir.getPath()).append("/router.info\n");
buf.append("router.keys.location=").append(baseDir.getPath()).append("/router.keys\n");
buf.append("router.networkDatabase.dbDir=").append(baseDir.getPath()).append("/netDb\n");
buf.append("router.tunnelPoolFile=").append(baseDir.getPath()).append("/tunnelPool.dat\n");
buf.append("router.keyBackupDir=").append(baseDir.getPath()).append("/keyBackup\n");
buf.append("router.clientConfigFile=").append(baseDir.getPath()).append("/clients.config\n");
buf.append("i2np.tcp.port=").append(basePort).append('\n');
buf.append("i2np.tcp.hostname=localhost\n");
buf.append("i2np.tcp.allowLocal=true\n");
buf.append("i2np.tcp.disable=true\n");
buf.append("i2np.tcp.enable=false\n");
buf.append("i2np.udp.host=127.0.0.1\n");
buf.append("i2np.udp.port=").append(basePort).append('\n');
buf.append("i2np.udp.internalPort=").append(basePort).append('\n');
buf.append("i2cp.port=").append(basePort+1).append('\n');
buf.append("stat.logFile=").append(baseDir.getPath()).append("/stats.log\n");
buf.append("stat.logFilters=*\n");
try {
FileOutputStream fos = new FileOutputStream(cfgFile);
fos.write(buf.toString().getBytes());
fos.close();
File envFile = new File(baseDir, "routerEnv.txt");
fos = new FileOutputStream(envFile);
fos.write(("loggerFilenameOverride="+baseDir+ "/logs/log-router-#.txt\n").getBytes());
fos.write(("router.configLocation="+baseDir+"/router.config\n").getBytes());
fos.write(("router.pingFile="+baseDir+"/router.ping\n").getBytes());
//fos.write(("i2p.vmCommSystem=true\n").getBytes());
//fos.write(("i2p.encryption=off\n").getBytes());
fos.close();
File f = new File(baseDir, "logs");
f.mkdirs();
if (isFirst) {
fos = new FileOutputStream(baseDir.getPath() + "/clients.config");
fos.write(("clientApp.0.args=" + (basePort-1) + " 127.0.0.1 ./webapps\n").getBytes());
fos.write(("clientApp.0.main=net.i2p.router.web.RouterConsoleRunner\n").getBytes());
fos.write(("clientApp.0.name=webconsole\n").getBytes());
fos.write(("clientApp.0.onBoot=true\n").getBytes());
fos.write(("clientApp.1.args=\n").getBytes());
fos.write(("clientApp.1.main=net.i2p.router.Counter\n").getBytes());
fos.write(("clientApp.1.name=counter\n").getBytes());
fos.write(("clientApp.1.onBoot=true\n").getBytes());
fos.write(("clientApp.2.args=i2ptunnel.config\n").getBytes());
fos.write(("clientApp.2.main=net.i2p.i2ptunnel.TunnelControllerGroup\n").getBytes());
fos.write(("clientApp.2.name=tunnels\n").getBytes());
fos.write(("clientApp.2.delay=60\n").getBytes());
fos.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
private static void usage() {
System.err.println("Usage: MultiRouterBuilder [routerDir routerPortStart]*");
}
}

View File

@ -27,6 +27,8 @@ class RouterThrottleImpl implements RouterThrottle {
private static final String PROP_MAX_TUNNELS = "router.maxParticipatingTunnels"; private static final String PROP_MAX_TUNNELS = "router.maxParticipatingTunnels";
private static final int DEFAULT_MAX_TUNNELS = 5000; private static final int DEFAULT_MAX_TUNNELS = 5000;
private static final String PROP_MAX_PROCESSINGTIME = "router.defaultProcessingTimeThrottle"; private static final String PROP_MAX_PROCESSINGTIME = "router.defaultProcessingTimeThrottle";
private static final long DEFAULT_REJECT_STARTUP_TIME = 20*60*1000;
private static final String PROP_REJECT_STARTUP_TIME = "router.rejectStartupTime";
/** /**
* TO BE FIXED - SEE COMMENTS BELOW * TO BE FIXED - SEE COMMENTS BELOW
@ -39,13 +41,12 @@ class RouterThrottleImpl implements RouterThrottle {
/** = TrivialPreprocessor.PREPROCESSED_SIZE */ /** = TrivialPreprocessor.PREPROCESSED_SIZE */
private static final int PREPROCESSED_SIZE = 1024; private static final int PREPROCESSED_SIZE = 1024;
private static final long REJECT_STARTUP_TIME = 20*60*1000;
public RouterThrottleImpl(RouterContext context) { public RouterThrottleImpl(RouterContext context) {
_context = context; _context = context;
_log = context.logManager().getLog(RouterThrottleImpl.class); _log = context.logManager().getLog(RouterThrottleImpl.class);
setTunnelStatus(); setTunnelStatus();
_context.simpleScheduler().addEvent(new ResetStatus(), REJECT_STARTUP_TIME + 120*1000); _context.simpleScheduler().addEvent(new ResetStatus(), 5*1000 + _context.getProperty(PROP_REJECT_STARTUP_TIME, DEFAULT_REJECT_STARTUP_TIME));
_context.statManager().createRateStat("router.throttleNetworkCause", "How lagged the jobQueue was when an I2NP was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 }); _context.statManager().createRateStat("router.throttleNetworkCause", "How lagged the jobQueue was when an I2NP was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
//_context.statManager().createRateStat("router.throttleNetDbCause", "How lagged the jobQueue was when a networkDb request was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 }); //_context.statManager().createRateStat("router.throttleNetDbCause", "How lagged the jobQueue was when a networkDb request was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
//_context.statManager().createRateStat("router.throttleTunnelCause", "How lagged the jobQueue was when a tunnel request was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 }); //_context.statManager().createRateStat("router.throttleTunnelCause", "How lagged the jobQueue was when a tunnel request was throttled", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
@ -114,7 +115,7 @@ class RouterThrottleImpl implements RouterThrottle {
} }
// Don't use CRIT because we don't want peers to think we're failing // Don't use CRIT because we don't want peers to think we're failing
if (_context.router().getUptime() < REJECT_STARTUP_TIME) { if (_context.router().getUptime() < DEFAULT_REJECT_STARTUP_TIME) {
setTunnelStatus(_x("Rejecting tunnels: Starting up")); setTunnelStatus(_x("Rejecting tunnels: Starting up"));
return TunnelHistory.TUNNEL_REJECT_BANDWIDTH; return TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
} }