forked from I2P_Developers/i2p.i2p

> Message-ID: <1776.202.37.75.101.1092369510.squirrel@202.37.75.101> > From: adam@adambuckley.net > To: jrandom@i2p.net > > [...] > > I hereby authorize my NtpClient.java and NtpMessage.java code to be > redistributed under the BSD license for the purpose of integration with > the I2P project, providing that I am credited as the original author of > the code. > > [...] w00t! adam++ code migrated into core/java/src/net/i2p/time, integrated with Clock, dropping that whole ugly pass-the-time-through-URL, and hence dropped support for :7655/setTime. New router.config properties to control the timestamper: time.sntpServerList=pool.ntp.org,pool.ntp.org,pool.ntp.org time.queryFrequencyMs=300000 time.disabled=false So, to disable, add time.disabled=true to your router.config. It is enabled by default. Default router.config and startup scripts updated accordingly (since timestamper.jar is now gone)
597 lines
24 KiB
Java
597 lines
24 KiB
Java
/*
|
||
* free (adj.): unencumbered; not under the control of others
|
||
* Written by jrandom in 2003 and released into the public domain
|
||
* with no warranty of any kind, either expressed or implied.
|
||
* It probably won't make your computer catch on fire, or eat
|
||
* your children, but it might. Use at your own risk.
|
||
*
|
||
*/
|
||
|
||
import java.io.BufferedReader;
|
||
import java.io.BufferedWriter;
|
||
import java.io.ByteArrayOutputStream;
|
||
import java.io.File;
|
||
import java.io.FileOutputStream;
|
||
import java.io.FileWriter;
|
||
import java.io.IOException;
|
||
import java.io.InputStream;
|
||
import java.io.InputStreamReader;
|
||
import java.net.URL;
|
||
import java.net.URLConnection;
|
||
import java.util.Date;
|
||
import java.util.HashMap;
|
||
import java.util.HashSet;
|
||
import java.util.Iterator;
|
||
import java.util.Properties;
|
||
import java.util.Set;
|
||
|
||
/**
|
||
* Please could someone write a real installer? Please.
|
||
* I should be shot for doing this.
|
||
*
|
||
* Note: this has dependencies upon how i2p/build.xml executes the "installer"
|
||
* task - namely that this class is in the jar "install.jar", and in that jar
|
||
* are the files COPYING, i2p.jar, i2ptunnel.jar, phttprelay.war, readme.txt,
|
||
* hosts.txt, and router.jar.
|
||
*
|
||
* Can you say "fragile code"?
|
||
* (oh well, enough caveats. commit)
|
||
*/
|
||
public abstract class Install {
|
||
private File _installDir;
|
||
private String _externalAddress;
|
||
private boolean _externalAddressIsReachable;
|
||
private int _inTCP;
|
||
private int _i2cpPort;
|
||
private String _phttpRegister;
|
||
private String _phttpSend;
|
||
private int _inBPS;
|
||
private int _outBPS;
|
||
private HashMap _answers;
|
||
private Properties _p;
|
||
|
||
private boolean _isWindows;
|
||
|
||
/**
|
||
* Show some installation status.
|
||
*/
|
||
public abstract void showStatus(String s);
|
||
|
||
/**
|
||
* Show an error when setting an option.
|
||
*/
|
||
public abstract void showOptError(String s);
|
||
|
||
/**
|
||
* Show some information about the following/preceding options
|
||
*/
|
||
public abstract void handleOptInfo(String s);
|
||
|
||
/**
|
||
* Start a new Option category
|
||
*/
|
||
public abstract void startOptCategory(String s);
|
||
|
||
|
||
/**
|
||
* Handle an option.
|
||
*/
|
||
public abstract void handleOption(int number, String question,
|
||
String def, String type);
|
||
/**
|
||
* Tell the installer that all options have been given.
|
||
* Install will not continue until this method has ended.
|
||
* When this method has ended, all options must have been set.
|
||
*/
|
||
public abstract void finishOptions();
|
||
|
||
/**
|
||
* Confirm an option. This can occur both while verifying options
|
||
* and later in the install process.
|
||
*/
|
||
public abstract boolean confirmOption(String question, boolean defaultYes);
|
||
|
||
public static void main(String args[]) {
|
||
Install install = new CliInstall();
|
||
install.runInstall();
|
||
}
|
||
|
||
public Install() {
|
||
_inTCP = -2;
|
||
_i2cpPort = -2;
|
||
_phttpRegister = null;
|
||
_phttpSend = null;
|
||
_inBPS = -2;
|
||
_outBPS = -2;
|
||
_externalAddressIsReachable = false;
|
||
}
|
||
|
||
public void runInstall() {
|
||
askQuestions();
|
||
detectOS();
|
||
configureAll();
|
||
createConfigFile();
|
||
createLoggerConfig();
|
||
createStartScript();
|
||
createReseedScript();
|
||
//createScripts("startIrcProxy.sh", "startIrcProxy.bat", 6668, "irc.duck.i2p", "log-irc-#.txt", "IRC Proxy", "IRC proxying scripts written to startIrcProxy", "Starting IRC proxy (when you see Ready! you can connect your IRC client to localhost:6668)");
|
||
//createScripts("startI2PCVSProxy.sh", "startI2PCVSProxy.bat", 2401, "i2pcvs.i2p", "log-i2pcvs-#.txt", "CVS Proxy", "Proxying scripts for I2P's CVS server written to startCVSProxy");
|
||
// only pulling them temporarily, duck, until the network is
|
||
// reliable enough
|
||
//createScripts("startJabber.sh", "startJabber.bat", 5222, "jabber.duck.i2p", "log-jabber-#.txt", "Jabber Proxy", "Squid proxying scripts written to startSquid");
|
||
//createScripts("startNntpProxy.sh", "startNntpProxy.bat", 1119, "nntp.duck.i2p", "log-nntp-#.txt", "NNTP Proxy","NNTP proxying scripts written to startNntpProxy");
|
||
createSeedNodes();
|
||
copyLibraries();
|
||
if (_isWindows) {
|
||
showStatus("To run the router, please run startRouter.bat in " + _installDir.getAbsolutePath());
|
||
} else {
|
||
showStatus("To run the router, please run startRouter.sh in " + _installDir.getAbsolutePath());
|
||
}
|
||
showStatus("");
|
||
}
|
||
|
||
private String numberTo4Digits(int number) {
|
||
String res = "0000"+number; // use four digit indices
|
||
return res.substring(res.length()-4);
|
||
}
|
||
|
||
private void askQuestions() {
|
||
try {
|
||
InputStream in = Install.class.getResourceAsStream("/install.config");
|
||
_p = new Properties();
|
||
_p.load(in);
|
||
in.close();
|
||
} catch (IOException ex) {
|
||
ex.printStackTrace();
|
||
System.exit(1);
|
||
}
|
||
int count = Integer.parseInt(_p.getProperty("qs.count"));
|
||
_answers = new HashMap(count+count); // load factor is 0.75, so
|
||
// there is some room left
|
||
for (int i=1;i<=count;i++) {
|
||
String ii = numberTo4Digits(i);
|
||
String question = _p.getProperty("qs."+ii+".question"),
|
||
param = _p.getProperty("qs."+ii+".param"),
|
||
type = _p.getProperty("qs."+ii+".type"),
|
||
def = _p.getProperty("qs."+ii+".default");
|
||
if (question == null) continue;
|
||
if (type == null || "info".equals(type)) {
|
||
// just print some text
|
||
handleOptInfo(question);
|
||
} else if ("info_spliced".equals(type)) {
|
||
// splice in some params already queried
|
||
handleOptInfo(handleSpliceParams(question));
|
||
} else if ("category".equals(type)) {
|
||
startOptCategory(question);
|
||
} else if ("skip".equals(type)) {
|
||
i = Integer.parseInt(question)-1;
|
||
} else { // a real question
|
||
if ("<none>".equals(question)) {
|
||
if (!setOption(i, def))
|
||
throw new RuntimeException("Fixed and invalid value");
|
||
} else {
|
||
handleOption(i,question,def,type);
|
||
}
|
||
}
|
||
}
|
||
finishOptions();
|
||
}
|
||
|
||
public /* overridable */ String handleSpliceParams(String s) {
|
||
return spliceParams(s);
|
||
}
|
||
|
||
public boolean setOption(int number, String answer) {
|
||
String ii = numberTo4Digits(number);
|
||
String param = _p.getProperty("qs."+ii+".param"),
|
||
type = _p.getProperty("qs."+ii+".type");
|
||
Object value = getOptionValue(answer, type);
|
||
if (value == null) {
|
||
return false;
|
||
} else {
|
||
if (param == null || value == null)
|
||
throw new NullPointerException();
|
||
_answers.put(param,value);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
private Object getOptionValue(String answer, String type) {
|
||
if ("string".equals(type)) {
|
||
// everything's okay till the very end
|
||
return answer;
|
||
} else if ("string>0".equals(type)) {
|
||
if (answer.length() > 0) {
|
||
return answer;
|
||
} else {
|
||
showOptError("Empty answers are not allowed.");
|
||
}
|
||
} else if ("directory".equals(type)) {
|
||
File f = new File(answer);
|
||
if (f.exists()) {
|
||
if (f.isDirectory()) {
|
||
showOptError("Using existing target directory " + f.getAbsolutePath());
|
||
return f;
|
||
} else {
|
||
showOptError("Location " + f.getAbsolutePath()+
|
||
" is not a directory. "+
|
||
"Lets try again");
|
||
}
|
||
} else {
|
||
boolean create = confirmOption("Target directory " + f.getAbsolutePath() +
|
||
" does not exist - create? ", false);
|
||
if (!create) {
|
||
showOptError("Lets try that again");
|
||
} else {
|
||
boolean created = f.mkdirs();
|
||
if (created) {
|
||
showOptError("Target directory " + f.getAbsolutePath() +
|
||
" created");
|
||
return f;
|
||
} else {
|
||
showOptError("Failed to create the "+
|
||
"directory. Lets choose another.");
|
||
}
|
||
}
|
||
}
|
||
} else if ("boolean".equals(type)) {
|
||
answer=answer.toLowerCase();
|
||
if ("yes".equals(answer) || "y".equals(answer))
|
||
answer="true";
|
||
if ("no".equals(answer) || "n".equals(answer))
|
||
answer="false";
|
||
if ("true".equals(answer) || "false".equals(answer)) {
|
||
return new Boolean("true".equals(answer));
|
||
}
|
||
showOptError("Incorrect boolean value, try `yes' <20>r `no'");
|
||
} else if ("numeric".equals(type) || "port".equals(type)) {
|
||
try {
|
||
int num = Integer.parseInt(answer);
|
||
if ("numeric".equals(type) ||
|
||
(num >0 && num < 65536)) {
|
||
return new Integer(num);
|
||
}
|
||
showOptError("Port number must be from 1 to 65535");
|
||
} catch (NumberFormatException ex) {
|
||
showOptError("Incorrect value: "+ex.getMessage());
|
||
}
|
||
} else if ("bandwidth".equals(type)) {
|
||
try {
|
||
answer = answer.toLowerCase();
|
||
int factor = 1;
|
||
// first check to see if it ends with m, k, or g
|
||
if (answer.endsWith("g"))
|
||
factor = 1024*1024*1024;
|
||
if (answer.endsWith("m"))
|
||
factor = 1024*1024;
|
||
if (answer.endsWith("k"))
|
||
factor = 1024;
|
||
if (factor > 1)
|
||
answer = answer.substring(0, answer.length()-1);
|
||
int val = factor * Integer.parseInt(answer);
|
||
if (val == -1 || val >0 ) {
|
||
return new Integer(val);
|
||
}
|
||
showOptError("Value must be -1 or positive.");
|
||
} catch (NumberFormatException ex) {
|
||
showOptError("Invalid number [" + answer + "]. Valid numbers are of the form -1, 42, 68k, 7m, 9g");
|
||
}
|
||
} else {
|
||
throw new RuntimeException ("cannot read installer option: " + type);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private String spliceParams(String s) {
|
||
StringBuffer txt = new StringBuffer(s.length()+100);
|
||
int ind;
|
||
while((ind = s.indexOf("##")) != -1) {
|
||
txt.append(s.substring(0,ind));
|
||
String temp = s.substring(ind+2);
|
||
ind = temp.indexOf("##");
|
||
if (ind == -1) throw new RuntimeException("Incorrect info_spliced param");
|
||
s=temp.substring(ind+2);
|
||
Object value = _answers.get(temp.substring(0,ind));
|
||
if (value == null) {
|
||
System.err.println("ERROR: Could not insert parameter "+temp.substring(0,ind));
|
||
System.exit(1);
|
||
} else {
|
||
txt.append(value.toString());
|
||
}
|
||
}
|
||
txt.append(s);
|
||
return txt.toString();
|
||
}
|
||
|
||
private void detectOS() {
|
||
String os = System.getProperty("os.name");
|
||
if (os.toLowerCase().indexOf("win") != -1)
|
||
_isWindows = true;
|
||
else
|
||
_isWindows = false;
|
||
// yes, this treats pre-os-x macs as unix, and perhaps some
|
||
// windows-esque OSes don't have "win" in their name, or some
|
||
// unix-esque OS does. fix when it occurs.
|
||
}
|
||
|
||
private void configureAll() {
|
||
_installDir = (File) _answers.get("installDir");
|
||
_externalAddress = _answers.get("externalAddress").toString();
|
||
_externalAddressIsReachable = ((Boolean)_answers.get("externalAddressIsReachable")).booleanValue();
|
||
|
||
_inTCP=((Integer)_answers.get("inTCP")).intValue();
|
||
_phttpRegister = _answers.get("phttpRegister").toString();
|
||
_phttpSend = _answers.get("phttpSend").toString();
|
||
_i2cpPort = ((Integer)_answers.get("i2cpPort")).intValue();
|
||
_inBPS = ((Integer)_answers.get("inBPS")).intValue();
|
||
_outBPS = ((Integer)_answers.get("outBPS")).intValue();
|
||
}
|
||
|
||
private void useTemplate(String templateName, File destFile) {
|
||
try {
|
||
BufferedWriter bw = new BufferedWriter(new FileWriter(destFile));
|
||
BufferedReader br = new BufferedReader(new InputStreamReader(Install.class.getResourceAsStream(templateName)));
|
||
String line;
|
||
while ((line = br.readLine()) != null) {
|
||
if (!line.startsWith("####")) {
|
||
bw.write(spliceParams(line));
|
||
bw.newLine();
|
||
}
|
||
}
|
||
br.close();
|
||
bw.close();
|
||
} catch (IOException ioe) {
|
||
ioe.printStackTrace();
|
||
System.exit(0);
|
||
}
|
||
}
|
||
|
||
private void createLoggerConfig() {
|
||
boolean verbose = ((Boolean)_answers.get("verboseLogs")).booleanValue();
|
||
createLogConfigOptions(verbose);
|
||
File logCfgFile = new File(_installDir, "logger.config");
|
||
useTemplate("logger.config.template",logCfgFile);
|
||
}
|
||
|
||
private void createSeedNodes() {
|
||
showStatus("To connect to I2P, you will need a reference to at least one other I2P router");
|
||
showStatus("Rather than bundle some (soon to be out of date) references with the software, ");
|
||
showStatus("you can either run the included reseed script or get get your own references ");
|
||
showStatus("from some out of band location. ");
|
||
showStatus("");
|
||
showStatus("The reseed script simply connects to http://i2p.net/i2pdb/ and downloads all");
|
||
showStatus("of the routerInfo-*.dat files and save them into " + (new File(_installDir, "i2pdb")).getAbsolutePath());
|
||
showStatus("That ../i2pdb/ directory is simply a mirror of one router's netDb directory, so those files");
|
||
showStatus("can come from anyone else too");
|
||
showStatus("");
|
||
showStatus("You can run the reseed script or download references (from your friends, etc) as often");
|
||
showStatus("as you like without restarting your router. If you find your netDb directory to have ");
|
||
showStatus("only one file in it (thats your router info), you will need more peers to get anything done.");
|
||
showStatus("");
|
||
boolean reseed = confirmOption("Do you want to run the reseed script now? ", true);
|
||
if (reseed) {
|
||
reseed();
|
||
} else {
|
||
showStatus("Ok ok, not reseeding - but please reseed before running the router");
|
||
}
|
||
}
|
||
|
||
private void reseed() {
|
||
try {
|
||
URL dir = new URL("http://i2p.net/i2pdb/");
|
||
String content = new String(readURL(dir));
|
||
Set urls = new HashSet();
|
||
int cur = 0;
|
||
while (true) {
|
||
int start = content.indexOf("href=\"routerInfo-", cur);
|
||
if (start < 0)
|
||
break;
|
||
|
||
int end = content.indexOf(".dat\">", start);
|
||
String name = content.substring(start+"href=\"routerInfo-".length(), end);
|
||
urls.add(name);
|
||
cur = end + 1;
|
||
}
|
||
|
||
for (Iterator iter = urls.iterator(); iter.hasNext(); ) {
|
||
fetchSeed((String)iter.next());
|
||
}
|
||
} catch (Throwable t) {
|
||
t.printStackTrace();
|
||
showStatus("Error reseeding - " + t.getMessage());
|
||
}
|
||
}
|
||
|
||
private void fetchSeed(String peer) throws Exception {
|
||
URL url = new URL("http://i2p.net/i2pdb/routerInfo-" + peer + ".dat");
|
||
showStatus("Fetching seed from " + url.toExternalForm());
|
||
|
||
byte data[] = readURL(url);
|
||
writeSeed(peer, data);
|
||
}
|
||
|
||
private byte[] readURL(URL url) throws Exception {
|
||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||
URLConnection con = url.openConnection();
|
||
InputStream in = con.getInputStream();
|
||
byte buf[] = new byte[1024];
|
||
while (true) {
|
||
int read = in.read(buf);
|
||
if (read < 0)
|
||
break;
|
||
baos.write(buf, 0, read);
|
||
}
|
||
in.close();
|
||
return baos.toByteArray();
|
||
}
|
||
|
||
private void writeSeed(String name, byte data[]) throws Exception {
|
||
File netDbDir = new File(_installDir, "netDb");
|
||
if (!netDbDir.exists())
|
||
netDbDir.mkdirs();
|
||
FileOutputStream fos = new FileOutputStream(new File(netDbDir, "routerInfo-" + name + ".dat"));
|
||
fos.write(data);
|
||
fos.close();
|
||
}
|
||
|
||
private void copyLibraries() {
|
||
File libDir = new File(_installDir, "lib");
|
||
if (!libDir.exists()) {
|
||
boolean libCreated = libDir.mkdirs();
|
||
if (!libCreated) {
|
||
showStatus("Error creating library directory " + libDir.getAbsolutePath());
|
||
return;
|
||
}
|
||
}
|
||
showStatus("Installing the libraries into " + libDir.getAbsolutePath());
|
||
int cnt = Integer.parseInt(_p.getProperty("libs.count"));
|
||
try {
|
||
for (int i=1;i<=cnt;i++) {
|
||
String ii = numberTo4Digits(i),
|
||
file = _p.getProperty("libs."+ii+".name");
|
||
boolean isLib = "true".equals(_p.getProperty("libs."+ii+".islib"));
|
||
InputStream is = Install.class.getResourceAsStream("/"+file);
|
||
if (is == null) throw new IOException("Resource /"+file+" not found");
|
||
copyFile(is, file, isLib?libDir:_installDir);
|
||
}
|
||
} catch (IOException ioe) {
|
||
showStatus("Error extracting the libraries: " + ioe.getMessage());
|
||
}
|
||
File dbDir = new File(_installDir, "netDb");
|
||
dbDir.mkdirs();
|
||
File logDir = new File(_installDir, "logs");
|
||
logDir.mkdirs();
|
||
}
|
||
|
||
private void copyFile(InputStream in, String name, File destDir) {
|
||
File destFile = new File(destDir, name);
|
||
try {
|
||
byte buf[] = new byte[16*1024];
|
||
FileOutputStream out = new FileOutputStream(destFile);
|
||
while (true) {
|
||
int read = in.read(buf);
|
||
if (read == -1)
|
||
break;
|
||
out.write(buf, 0, read);
|
||
}
|
||
in.close();
|
||
out.close();
|
||
showStatus("Installed file " + destFile.getName() + " in " + destFile.getParent());
|
||
} catch (IOException ioe) {
|
||
showStatus("Error saving " + name + " to " + destFile.getAbsolutePath()
|
||
+ ": " + ioe.getMessage());
|
||
}
|
||
}
|
||
|
||
private void createLogConfigOptions(boolean verbose) {
|
||
_answers.put("_logger_level", verbose?"DEBUG":"INFO");
|
||
_answers.put("_logger_level2", verbose?"WARN":"ERROR");
|
||
StringBuffer buf = new StringBuffer();
|
||
if (!verbose) {
|
||
// overrides for particularly chatty classes
|
||
_answers.put("_logger_notverbose", "logger.record.net.i2p.router.transport.Triv=ERROR"+NL+
|
||
"logger.record.net.i2p.router.transport.Band=ERROR"+NL+
|
||
"logger.record.net.i2p.crypto=ERROR" +NL+
|
||
"logger.record.net.i2p.crypto.DH=ERROR");
|
||
} else {
|
||
_answers.put("_logger_notverbose","");
|
||
}
|
||
}
|
||
|
||
private void createScripts(String unixName, String windowsName, int listenPort,
|
||
String targetDest, String logfilePattern, String windowTitle,
|
||
String message, String scriptMessage) {
|
||
createScripts(unixName, windowsName, "client "+listenPort+" "+targetDest,
|
||
logfilePattern, windowTitle, message, scriptMessage);
|
||
}
|
||
|
||
private void createScripts(String unixName, String windowsName, String command,
|
||
String logfilePattern, String windowTitle, String message,
|
||
String scriptMessage) {
|
||
_answers.put("_scripts_port", ""+_i2cpPort);
|
||
_answers.put("_scripts_cmd", command);
|
||
_answers.put("_scripts_logname", logfilePattern);
|
||
_answers.put("_scripts_winttl", windowTitle);
|
||
_answers.put("_scripts_message", scriptMessage);
|
||
if (_isWindows) {
|
||
File windowsFile = new File(_installDir, windowsName);
|
||
useTemplate("startFoo.bat.template", windowsFile);
|
||
} else {
|
||
File unixFile = new File(_installDir, unixName);
|
||
useTemplate("startFoo.sh.template", unixFile);
|
||
chmodaplusx(unixFile);
|
||
}
|
||
showStatus(message);
|
||
}
|
||
|
||
private void createReseedScript() {
|
||
if (_isWindows) {
|
||
File windowsFile = new File(_installDir, "reseed.bat");
|
||
useTemplate("reseed.bat.template", windowsFile);
|
||
} else {
|
||
File unixFile = new File(_installDir, "reseed.sh");
|
||
useTemplate("reseed.sh.template", unixFile);
|
||
chmodaplusx(unixFile);
|
||
}
|
||
}
|
||
|
||
private void chmodaplusx(File f) {
|
||
try {
|
||
Runtime.getRuntime().exec("chmod a+x " + f.getAbsolutePath());
|
||
} catch (IOException ioe) {
|
||
showStatus("Error setting "+f.getName()+" as executable");
|
||
}
|
||
}
|
||
|
||
private void createStartScript() {
|
||
_answers.put("_scripts_installdir", _installDir.getAbsolutePath());
|
||
if (_isWindows) {
|
||
File windowsFile = new File(_installDir, "startRouter.bat");
|
||
useTemplate("startRouter.bat.template", windowsFile);
|
||
} else {
|
||
File unixFile = new File(_installDir, "startRouter.sh");
|
||
useTemplate("startRouter.sh.template", unixFile);
|
||
File unixStopFile = new File(_installDir, "stopRouter.sh");
|
||
useTemplate("stopRouter.sh.template", unixStopFile);
|
||
chmodaplusx(unixFile);
|
||
chmodaplusx(unixStopFile);
|
||
}
|
||
}
|
||
|
||
private void createConfigFile() {
|
||
File configFile = new File(_installDir, "router.config");
|
||
setConfigFileOptions();
|
||
useTemplate("router.config.template", configFile);
|
||
showStatus("Router configuration file written to " + configFile.getAbsolutePath());
|
||
showStatus("");
|
||
}
|
||
|
||
private final static String NL = System.getProperty("line.separator");
|
||
|
||
private void setConfigFileOptions() {
|
||
// set fields needed for the config template
|
||
_answers.put("NOW", new Date().toString());
|
||
if (_inTCP <= 0) {
|
||
_answers.put("_router_hn", "#i2np.tcp.hostname=[externally reachable hostname or IP address goes here]");
|
||
_answers.put("_router_port", "#i2np.tcp.port=[TCP/IP port number]");
|
||
_answers.put("_router_lavalid","#i2np.tcp.listenAddressIsValid=[true/false for whether your external address is locally reachable]");
|
||
_answers.put("_router_tcpdisable","#i2np.tcp.disable=[true/false for whether you want absolutely no tcp connections to be established (forcing phttp, etc)])");
|
||
} else {
|
||
_answers.put("_router_hn","i2np.tcp.hostname="+_externalAddress);
|
||
_answers.put("_router_port","i2np.tcp.port="+_inTCP);
|
||
_answers.put("_router_lavalid","i2np.tcp.listenAddressIsValid="+_externalAddressIsReachable);
|
||
_answers.put("_router_tcpdisable","i2np.tcp.disable=false");
|
||
}
|
||
if ( (_phttpRegister == null) || (_phttpSend == null) ) {
|
||
_answers.put("_router_phttpreg","#i2np.phttp.registerURL=[full URL to a PHTTP registration server, e.g. http://someHost:8080/phttprelay/phttpRegister]");
|
||
_answers.put("_router_phttpsend","#i2np.phttp.sendURL=[full URL to a PHTTP relay server, e.g. http://someHost:8080/phttprelay/phttpSend]");
|
||
} else {
|
||
_answers.put("_router_phttpreg","i2np.phttp.registerURL="+_phttpRegister);
|
||
_answers.put("_router_phttpsend","i2np.phttp.sendURL="+_phttpSend);
|
||
}
|
||
_answers.put("_router_i2cp_port",""+_i2cpPort);
|
||
_answers.put("_router_inbps",""+(_inBPS*60));
|
||
_answers.put("_router_outbps",""+(_outBPS*60));
|
||
}
|
||
}
|