forked from I2P_Developers/i2p.i2p
merge of '50335c064a9992f4ba8707d62d35bbbbe752d231'
and 'b93c1c7b2b01fc43af5bc07470d9997f3edba6da'
This commit is contained in:
@@ -38,7 +38,7 @@ import net.i2p.util.EepGet;
|
||||
* @author Ragnarok
|
||||
*
|
||||
*/
|
||||
public class AddressBook {
|
||||
class AddressBook {
|
||||
|
||||
private String location;
|
||||
|
||||
@@ -88,6 +88,8 @@ public class AddressBook {
|
||||
* read or cannot be read, return an empty AddressBook.
|
||||
* Set a maximum size of the remote book to make it a little harder for a malicious book-sender.
|
||||
*
|
||||
* Yes, the EepGet fetch() is done in this constructor.
|
||||
*
|
||||
* @param subscription
|
||||
* A Subscription instance pointing at a remote address book.
|
||||
* @param proxyHost hostname of proxy
|
||||
@@ -102,6 +104,7 @@ public class AddressBook {
|
||||
if (get.fetch()) {
|
||||
subscription.setEtag(get.getETag());
|
||||
subscription.setLastModified(get.getLastModified());
|
||||
subscription.setLastFetched(I2PAppContext.getGlobalContext().clock().now());
|
||||
}
|
||||
try {
|
||||
this.addresses = ConfigParser.parse(tmp);
|
||||
|
@@ -35,6 +35,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.util.SecureFile;
|
||||
import net.i2p.util.SecureFileOutputStream;
|
||||
|
||||
/**
|
||||
@@ -46,7 +47,7 @@ import net.i2p.util.SecureFileOutputStream;
|
||||
*
|
||||
* @author Ragnarok
|
||||
*/
|
||||
public class ConfigParser {
|
||||
class ConfigParser {
|
||||
|
||||
/**
|
||||
* Strip the comments from a String. Lines that begin with '#' and ';' are
|
||||
@@ -142,7 +143,7 @@ public class ConfigParser {
|
||||
* @param file
|
||||
* A File to attempt to parse.
|
||||
* @param map
|
||||
* A Map to use as the default, if file fails.
|
||||
* A Map containing values to use as defaults.
|
||||
* @return A Map containing the key, value pairs from file, or if file
|
||||
* cannot be read, map.
|
||||
*/
|
||||
@@ -150,6 +151,11 @@ public class ConfigParser {
|
||||
Map result;
|
||||
try {
|
||||
result = ConfigParser.parse(file);
|
||||
for (Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
|
||||
String key = (String) iter.next();
|
||||
if (!result.containsKey(key))
|
||||
result.put(key, map.get(key));
|
||||
}
|
||||
} catch (IOException exp) {
|
||||
result = map;
|
||||
try {
|
||||
@@ -280,7 +286,7 @@ public class ConfigParser {
|
||||
* if file cannot be written to.
|
||||
*/
|
||||
public static void write(Map map, File file) throws IOException {
|
||||
File tmp = File.createTempFile("hoststxt-", ".tmp", file.getAbsoluteFile().getParentFile());
|
||||
File tmp = SecureFile.createTempFile("hoststxt-", ".tmp", file.getAbsoluteFile().getParentFile());
|
||||
ConfigParser
|
||||
.write(map, new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(tmp), "UTF-8")));
|
||||
boolean success = tmp.renameTo(file);
|
||||
|
@@ -38,7 +38,7 @@ import net.i2p.util.SecureDirectory;
|
||||
*
|
||||
*/
|
||||
public class Daemon {
|
||||
public static final String VERSION = "2.0.3";
|
||||
public static final String VERSION = "2.0.4";
|
||||
private static final Daemon _instance = new Daemon();
|
||||
private boolean _running;
|
||||
|
||||
@@ -66,6 +66,7 @@ public class Daemon {
|
||||
router.merge(master, true, null);
|
||||
Iterator iter = subscriptions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
// yes, the EepGet fetch() is done in next()
|
||||
router.merge((AddressBook) iter.next(), false, log);
|
||||
}
|
||||
router.write();
|
||||
@@ -97,6 +98,15 @@ public class Daemon {
|
||||
File etagsFile = new File(home, (String) settings.get("etags"));
|
||||
File lastModifiedFile = new File(home, (String) settings
|
||||
.get("last_modified"));
|
||||
File lastFetchedFile = new File(home, (String) settings
|
||||
.get("last_fetched"));
|
||||
long delay;
|
||||
try {
|
||||
delay = Long.parseLong((String) settings.get("update_delay"));
|
||||
} catch (NumberFormatException nfe) {
|
||||
delay = 12;
|
||||
}
|
||||
delay *= 60 * 60 * 1000;
|
||||
|
||||
AddressBook master = new AddressBook(masterFile);
|
||||
AddressBook router = new AddressBook(routerFile);
|
||||
@@ -106,7 +116,7 @@ public class Daemon {
|
||||
defaultSubs.add("http://www.i2p2.i2p/hosts.txt");
|
||||
|
||||
SubscriptionList subscriptions = new SubscriptionList(subscriptionFile,
|
||||
etagsFile, lastModifiedFile, defaultSubs, (String) settings
|
||||
etagsFile, lastModifiedFile, lastFetchedFile, delay, defaultSubs, (String) settings
|
||||
.get("proxy_host"), Integer.parseInt((String) settings.get("proxy_port")));
|
||||
Log log = new Log(logFile);
|
||||
|
||||
@@ -150,6 +160,7 @@ public class Daemon {
|
||||
defaultSettings.put("subscriptions", "subscriptions.txt");
|
||||
defaultSettings.put("etags", "etags");
|
||||
defaultSettings.put("last_modified", "last_modified");
|
||||
defaultSettings.put("last_fetched", "last_fetched");
|
||||
defaultSettings.put("update_delay", "12");
|
||||
|
||||
if (!homeFile.exists()) {
|
||||
@@ -165,7 +176,7 @@ public class Daemon {
|
||||
Map settings = ConfigParser.parse(settingsFile, defaultSettings);
|
||||
// wait
|
||||
try {
|
||||
Thread.sleep(5*60*1000);
|
||||
Thread.sleep(5*60*1000 + I2PAppContext.getGlobalContext().random().nextLong(5*60*1000));
|
||||
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
|
||||
} catch (InterruptedException ie) {}
|
||||
|
||||
|
@@ -27,7 +27,7 @@ package net.i2p.addressbook;
|
||||
* @author Ragnarok
|
||||
*
|
||||
*/
|
||||
public class DaemonThread extends Thread {
|
||||
class DaemonThread extends Thread {
|
||||
|
||||
private String[] args;
|
||||
|
||||
|
@@ -33,7 +33,7 @@ import java.util.Date;
|
||||
* @author Ragnarok
|
||||
*
|
||||
*/
|
||||
public class Log {
|
||||
class Log {
|
||||
|
||||
private File file;
|
||||
|
||||
|
@@ -27,13 +27,14 @@ package net.i2p.addressbook;
|
||||
* @author Ragnarok
|
||||
*
|
||||
*/
|
||||
public class Subscription {
|
||||
class Subscription {
|
||||
|
||||
private String location;
|
||||
|
||||
private String etag;
|
||||
|
||||
private String lastModified;
|
||||
private long lastFetched;
|
||||
|
||||
/**
|
||||
* Construct a Subscription pointing to the address book at location, that
|
||||
@@ -47,11 +48,17 @@ public class Subscription {
|
||||
* @param lastModified
|
||||
* the last-modified header we recieved the last time we read
|
||||
* this subscription.
|
||||
* @param lastFetched when the subscription was last fetched (Java time, as a String)
|
||||
*/
|
||||
public Subscription(String location, String etag, String lastModified) {
|
||||
public Subscription(String location, String etag, String lastModified, String lastFetched) {
|
||||
this.location = location;
|
||||
this.etag = etag;
|
||||
this.lastModified = lastModified;
|
||||
if (lastFetched != null) {
|
||||
try {
|
||||
this.lastFetched = Long.parseLong(lastFetched);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,4 +109,14 @@ public class Subscription {
|
||||
public void setLastModified(String lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 0.8.2 */
|
||||
public long getLastFetched() {
|
||||
return this.lastFetched;
|
||||
}
|
||||
|
||||
/** @since 0.8.2 */
|
||||
public void setLastFetched(long t) {
|
||||
this.lastFetched = t;
|
||||
}
|
||||
}
|
||||
|
@@ -21,31 +21,39 @@
|
||||
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.DataHelper; // debug
|
||||
|
||||
/**
|
||||
* An iterator over the subscriptions in a SubscriptionList. Note that this iterator
|
||||
* returns AddressBook objects, and not Subscription objects.
|
||||
* Yes, the EepGet fetch() is done in here in next().
|
||||
*
|
||||
* @author Ragnarok
|
||||
*/
|
||||
public class SubscriptionIterator implements Iterator {
|
||||
class SubscriptionIterator implements Iterator {
|
||||
|
||||
private Iterator subIterator;
|
||||
private String proxyHost;
|
||||
private int proxyPort;
|
||||
private final long delay;
|
||||
|
||||
/**
|
||||
* Construct a SubscriptionIterator using the Subscriprions in List subscriptions.
|
||||
*
|
||||
* @param subscriptions
|
||||
* List of Subscription objects that represent address books.
|
||||
* @param delay the minimum delay since last fetched for the iterator to actually fetch
|
||||
* @param proxyHost proxy hostname
|
||||
* @param proxyPort proxt port number
|
||||
*/
|
||||
public SubscriptionIterator(List subscriptions, String proxyHost, int proxyPort) {
|
||||
public SubscriptionIterator(List subscriptions, long delay, String proxyHost, int proxyPort) {
|
||||
this.subIterator = subscriptions.iterator();
|
||||
this.delay = delay;
|
||||
this.proxyHost = proxyHost;
|
||||
this.proxyPort = proxyPort;
|
||||
}
|
||||
@@ -58,12 +66,24 @@ public class SubscriptionIterator implements Iterator {
|
||||
return this.subIterator.hasNext();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.util.Iterator#next()
|
||||
/**
|
||||
* Yes, the EepGet fetch() is done in here in next().
|
||||
*
|
||||
* see java.util.Iterator#next()
|
||||
* @return an AddressBook (empty if the minimum delay has not been met)
|
||||
*/
|
||||
public Object next() {
|
||||
Subscription sub = (Subscription) this.subIterator.next();
|
||||
return new AddressBook(sub, this.proxyHost, this.proxyPort);
|
||||
if (sub.getLastFetched() + this.delay < I2PAppContext.getGlobalContext().clock().now()) {
|
||||
//System.err.println("Fetching addressbook from " + sub.getLocation());
|
||||
return new AddressBook(sub, this.proxyHost, this.proxyPort);
|
||||
} else {
|
||||
//System.err.println("Addressbook " + sub.getLocation() + " was last fetched " +
|
||||
// DataHelper.formatDuration(I2PAppContext.getGlobalContext().clock().now() - sub.getLastFetched()) +
|
||||
// " ago but the minimum delay is " +
|
||||
// DataHelper.formatDuration(this.delay));
|
||||
return new AddressBook(Collections.EMPTY_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -72,4 +92,4 @@ public class SubscriptionIterator implements Iterator {
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,13 +35,15 @@ import java.util.Map;
|
||||
* @author Ragnarok
|
||||
*
|
||||
*/
|
||||
public class SubscriptionList {
|
||||
class SubscriptionList {
|
||||
|
||||
private List subscriptions;
|
||||
|
||||
private File etagsFile;
|
||||
|
||||
private File lastModifiedFile;
|
||||
private File lastFetchedFile;
|
||||
private final long delay;
|
||||
|
||||
private String proxyHost;
|
||||
|
||||
@@ -60,20 +62,24 @@ public class SubscriptionList {
|
||||
* @param lastModifiedFile
|
||||
* A file containg the last-modified headers used for conditional
|
||||
* GET. The file is in the format "url=leastmodified".
|
||||
* @param delay the minimum delay since last fetched for the iterator to actually fetch
|
||||
* @param defaultSubs default subscription file
|
||||
* @param proxyHost proxy hostname
|
||||
* @param proxyPort proxy port number
|
||||
*/
|
||||
public SubscriptionList(File locationsFile, File etagsFile,
|
||||
File lastModifiedFile, List defaultSubs, String proxyHost,
|
||||
File lastModifiedFile, File lastFetchedFile, long delay, List defaultSubs, String proxyHost,
|
||||
int proxyPort) {
|
||||
this.subscriptions = new LinkedList();
|
||||
this.etagsFile = etagsFile;
|
||||
this.lastModifiedFile = lastModifiedFile;
|
||||
this.lastFetchedFile = lastFetchedFile;
|
||||
this.delay = delay;
|
||||
this.proxyHost = proxyHost;
|
||||
this.proxyPort = proxyPort;
|
||||
Map etags;
|
||||
Map lastModified;
|
||||
Map lastFetched;
|
||||
String location;
|
||||
List locations = ConfigParser.parseSubscriptions(locationsFile,
|
||||
defaultSubs);
|
||||
@@ -87,11 +93,17 @@ public class SubscriptionList {
|
||||
} catch (IOException exp) {
|
||||
lastModified = new HashMap();
|
||||
}
|
||||
try {
|
||||
lastFetched = ConfigParser.parse(lastFetchedFile);
|
||||
} catch (IOException exp) {
|
||||
lastFetched = new HashMap();
|
||||
}
|
||||
Iterator iter = locations.iterator();
|
||||
while (iter.hasNext()) {
|
||||
location = (String) iter.next();
|
||||
this.subscriptions.add(new Subscription(location, (String) etags
|
||||
.get(location), (String) lastModified.get(location)));
|
||||
this.subscriptions.add(new Subscription(location, (String) etags.get(location),
|
||||
(String) lastModified.get(location),
|
||||
(String) lastFetched.get(location)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,18 +114,22 @@ public class SubscriptionList {
|
||||
* @return A SubscriptionIterator.
|
||||
*/
|
||||
public SubscriptionIterator iterator() {
|
||||
return new SubscriptionIterator(this.subscriptions, this.proxyHost,
|
||||
return new SubscriptionIterator(this.subscriptions, this.delay, this.proxyHost,
|
||||
this.proxyPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the etag and last-modified headers for each Subscription to files.
|
||||
* Write the etag and last-modified headers,
|
||||
* and the last-fetched time, for each Subscription to files.
|
||||
* BUG - If the subscription URL is a cgi containing an '=' the files
|
||||
* won't be read back correctly; the '=' should be escaped.
|
||||
*/
|
||||
public void write() {
|
||||
Iterator iter = this.subscriptions.iterator();
|
||||
Subscription sub;
|
||||
Map etags = new HashMap();
|
||||
Map lastModified = new HashMap();
|
||||
Map lastFetched = new HashMap();
|
||||
while (iter.hasNext()) {
|
||||
sub = (Subscription) iter.next();
|
||||
if (sub.getEtag() != null) {
|
||||
@@ -122,11 +138,13 @@ public class SubscriptionList {
|
||||
if (sub.getLastModified() != null) {
|
||||
lastModified.put(sub.getLocation(), sub.getLastModified());
|
||||
}
|
||||
lastFetched.put(sub.getLocation(), "" + sub.getLastFetched());
|
||||
}
|
||||
try {
|
||||
ConfigParser.write(etags, this.etagsFile);
|
||||
ConfigParser.write(lastModified, this.lastModifiedFile);
|
||||
ConfigParser.write(lastFetched, this.lastFetchedFile);
|
||||
} catch (IOException exp) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import net.i2p.util.EepGet;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
import net.i2p.util.SecureFile;
|
||||
import net.i2p.util.SimpleScheduler;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
import net.i2p.util.Translate;
|
||||
@@ -244,7 +245,7 @@ public class I2PSnarkUtil {
|
||||
File out = null;
|
||||
try {
|
||||
// we could use the system tmp dir but deleteOnExit() doesn't seem to work on all platforms...
|
||||
out = File.createTempFile("i2psnark", null, _tmpDir);
|
||||
out = SecureFile.createTempFile("i2psnark", null, _tmpDir);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
if (out != null)
|
||||
|
@@ -29,6 +29,7 @@ import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.crypto.SHA1;
|
||||
import net.i2p.util.SecureFile;
|
||||
|
||||
/**
|
||||
* Maintains pieces on disk. Can be used to store and retrieve pieces.
|
||||
@@ -462,7 +463,7 @@ public class Storage
|
||||
/** use a saved bitfield and timestamp from a config file */
|
||||
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
|
||||
{
|
||||
File base = new File(rootDir, filterName(metainfo.getName()));
|
||||
File base = new SecureFile(rootDir, filterName(metainfo.getName()));
|
||||
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
|
||||
|
||||
List files = metainfo.getFiles();
|
||||
@@ -623,7 +624,7 @@ public class Storage
|
||||
else
|
||||
{
|
||||
// The final element (file) in the hierarchy.
|
||||
f = new File(base, name);
|
||||
f = new SecureFile(base, name);
|
||||
if (!f.createNewFile() && !f.exists())
|
||||
throw new IOException("Could not create file " + f);
|
||||
}
|
||||
|
@@ -174,6 +174,8 @@ public class I2PSnarkServlet extends Default {
|
||||
"<head><link rel=\"shortcut icon\" href=\"/themes/snark/ubergine/favicon.ico\">\n" +
|
||||
"<title>");
|
||||
out.write(_("I2PSnark - Anonymous BitTorrent Client"));
|
||||
if ("2".equals(peerParam))
|
||||
out.write(" | Debug Mode");
|
||||
out.write("</title>\n");
|
||||
|
||||
// we want it to go to the base URI so we don't refresh with some funky action= value
|
||||
@@ -780,14 +782,15 @@ public class I2PSnarkServlet extends Default {
|
||||
// temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash
|
||||
String announce = snark.meta.getAnnounce();
|
||||
if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr") ||
|
||||
announce.startsWith("http://lnQ6yoBT") || announce.startsWith("http://tracker2.postman.i2p/")) {
|
||||
announce.startsWith("http://lnQ6yoBT") || announce.startsWith("http://tracker2.postman.i2p/") || announce.startsWith("http://ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna.b32.i2p/")) {
|
||||
Map trackers = _manager.getTrackers();
|
||||
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String name = (String)entry.getKey();
|
||||
String baseURL = (String)entry.getValue();
|
||||
if (!(baseURL.startsWith(announce) || // vvv hack for non-b64 announce in list vvv
|
||||
(announce.startsWith("http://lnQ6yoBT") && baseURL.startsWith("http://tracker2.postman.i2p/"))))
|
||||
(announce.startsWith("http://lnQ6yoBT") && baseURL.startsWith("http://tracker2.postman.i2p/")) ||
|
||||
(announce.startsWith("http://ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna.b32.i2p/") && baseURL.startsWith("http://tracker2.postman.i2p/"))))
|
||||
continue;
|
||||
int e = baseURL.indexOf('=');
|
||||
if (e < 0)
|
||||
@@ -1552,11 +1555,11 @@ public class I2PSnarkServlet extends Default {
|
||||
icon = "photo";
|
||||
else if (mime.startsWith("audio/") || mime.equals("application/ogg") ||
|
||||
plc.endsWith(".flac") || plc.endsWith(".m4a") || plc.endsWith(".wma") ||
|
||||
plc.endsWith(".ape"))
|
||||
plc.endsWith(".ape") || plc.endsWith(".oga"))
|
||||
icon = "music";
|
||||
else if (mime.startsWith("video/") || plc.endsWith(".mkv") || plc.endsWith(".m4v") ||
|
||||
plc.endsWith(".mp4") || plc.endsWith(".wmv") || plc.endsWith(".flv") ||
|
||||
plc.endsWith(".ogm"))
|
||||
plc.endsWith(".ogm") || plc.endsWith(".ogv"))
|
||||
icon = "film";
|
||||
else if (mime.equals("application/zip") || mime.equals("application/x-gtar") ||
|
||||
mime.equals("application/compress") || mime.equals("application/gzip") ||
|
||||
|
@@ -85,8 +85,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
|
||||
public boolean ownDest = false;
|
||||
|
||||
/** the I2CP port */
|
||||
public String port = System.getProperty(I2PClient.PROP_TCP_PORT, "7654");
|
||||
/** the I2CP host */
|
||||
public String host = System.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
|
||||
/** the listen-on host. Sadly the listen-on port does not have a field. */
|
||||
public String listenHost = host;
|
||||
|
||||
public long readTimeout = -1;
|
||||
@@ -689,8 +692,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
addtask(task);
|
||||
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.error(getPrefix() + "Invalid I2PTunnel config to create a client [" + host + ":"+ port + "]", iae);
|
||||
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
|
||||
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
|
||||
" and listening on " + listenHost + ':' + port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("clientTaskId", Integer.valueOf(-1));
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
@@ -763,8 +768,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
addtask(task);
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ clientPort + "]", iae);
|
||||
l.log("Invalid I2PTunnel configuration [" + host + ":" + clientPort + "]");
|
||||
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
|
||||
" and listening on " + listenHost + ':' + port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
@@ -829,7 +836,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.error(getPrefix() + "Invalid I2PTunnel config to create a connect client [" + host + ":"+ _port + "]", iae);
|
||||
String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at " + host + ':'+ port +
|
||||
" and listening on " + listenHost + ':' + port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
|
||||
@@ -892,8 +902,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
addtask(task);
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.error(getPrefix() + "Invalid I2PTunnel config to create an ircclient [" + host + ":"+ _port + "]", iae);
|
||||
l.log("Invalid I2PTunnel configuration [" + host + ":" + _port + "]");
|
||||
String msg = "Invalid I2PTunnel configuration to create an IRC client connecting to the router at " + host + ':'+ port +
|
||||
" and listening on " + listenHost + ':' + port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
|
||||
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
|
||||
// Otherwise, the tunnel stays up even though the port is down
|
||||
@@ -939,10 +951,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
isShared = "true".equalsIgnoreCase(args[1].trim());
|
||||
|
||||
ownDest = !isShared;
|
||||
I2PTunnelTask task;
|
||||
task = new I2PSOCKSTunnel(_port, l, ownDest, (EventDispatcher) this, this, null);
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
|
||||
try {
|
||||
I2PTunnelTask task = new I2PSOCKSTunnel(_port, l, ownDest, (EventDispatcher) this, this, null);
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a SOCKS Proxy connecting to the router at " + host + ':'+ port +
|
||||
" and listening on " + listenHost + ':' + port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
l.log("sockstunnel <port>");
|
||||
l.log(" creates a tunnel that distributes SOCKS requests.");
|
||||
@@ -978,10 +998,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
String privateKeyFile = null;
|
||||
if (args.length == 3)
|
||||
privateKeyFile = args[2];
|
||||
I2PTunnelTask task;
|
||||
task = new I2PSOCKSIRCTunnel(_port, l, ownDest, (EventDispatcher) this, this, privateKeyFile);
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
|
||||
try {
|
||||
I2PTunnelTask task = new I2PSOCKSIRCTunnel(_port, l, ownDest, (EventDispatcher) this, this, privateKeyFile);
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a SOCKS IRC Proxy connecting to the router at " + host + ':'+ port +
|
||||
" and listening on " + listenHost + ':' + port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
l.log("socksirctunnel <port> [<sharedClient> [<privKeyFile>]]");
|
||||
l.log(" creates a tunnel for SOCKS IRC.");
|
||||
@@ -1019,10 +1047,19 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
if (_port <= 0)
|
||||
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
|
||||
|
||||
StreamrConsumer task = new StreamrConsumer(_host, _port, args[2], l, (EventDispatcher) this, this);
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId()));
|
||||
try {
|
||||
StreamrConsumer task = new StreamrConsumer(_host, _port, args[2], l, (EventDispatcher) this, this);
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a Streamr Client connecting to the router at " + host + ':'+ port +
|
||||
" and sending to " + _host + ':' + port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("streamrtunnnelTaskId", Integer.valueOf(-1));
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
l.log("streamrclient <host> <port> <destination>");
|
||||
l.log(" creates a tunnel that receives streaming data.");
|
||||
@@ -1409,7 +1446,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
for (Iterator it = tasks.iterator(); it.hasNext();) {
|
||||
I2PTunnelTask t = (I2PTunnelTask) it.next();
|
||||
int id = t.getId();
|
||||
_log.debug(getPrefix() + "closetask(): parsing task " + id + " (" + t.toString() + ")");
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(getPrefix() + "closetask(): parsing task " + id + " (" + t.toString() + ")");
|
||||
if (id == num) {
|
||||
closed = closetask(t, forced, l);
|
||||
break;
|
||||
@@ -1427,9 +1465,13 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
*
|
||||
*/
|
||||
private boolean closetask(I2PTunnelTask t, boolean forced, Logging l) {
|
||||
l.log("Closing task " + t.getId() + (forced ? " forced..." : "..."));
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Closing task " + t.getId() + (forced ? " forced..." : "..."));
|
||||
//l.log("Closing task " + t.getId() + (forced ? " forced..." : "..."));
|
||||
if (t.close(forced)) {
|
||||
l.log("Task " + t.getId() + " closed.");
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Task " + t.getId() + " closed.");
|
||||
//l.log("Task " + t.getId() + " closed.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@@ -128,10 +128,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
configurePool(tunnel);
|
||||
|
||||
if (open && listenerReady) {
|
||||
l.log("Ready! Port " + getLocalPort());
|
||||
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
|
||||
notifyEvent("openBaseClientResult", "ok");
|
||||
} else {
|
||||
l.log("Error listening - please see the logs!");
|
||||
l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs");
|
||||
notifyEvent("openBaseClientResult", "error");
|
||||
}
|
||||
}
|
||||
@@ -181,7 +181,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
while (sockMgr == null) {
|
||||
verifySocketManager();
|
||||
if (sockMgr == null) {
|
||||
_log.log(Log.CRIT, "Unable to create socket manager (our own? " + ownDest + ")");
|
||||
_log.error("Unable to connect to router and build tunnels for " + handlerName);
|
||||
// FIXME there is a loop in buildSocketManager(), do we really need another one here?
|
||||
// no matter, buildSocketManager() now throws an IllegalArgumentException
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
@@ -212,12 +214,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
|
||||
if (open && listenerReady) {
|
||||
if (openNow)
|
||||
l.log("Ready! Port " + getLocalPort());
|
||||
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
|
||||
else
|
||||
l.log("Listening on port " + getLocalPort() + ", delaying tunnel open until required");
|
||||
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort + ", delaying tunnel open until required");
|
||||
notifyEvent("openBaseClientResult", "ok");
|
||||
} else {
|
||||
l.log("Error listening - please see the logs!");
|
||||
l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs");
|
||||
notifyEvent("openBaseClientResult", "error");
|
||||
}
|
||||
}
|
||||
@@ -257,6 +259,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
* Sets the this.sockMgr field if it is null, or if we want a new one
|
||||
*
|
||||
* We need a socket manager before getDefaultOptions() and most other things
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected void verifySocketManager() {
|
||||
synchronized(sockLock) {
|
||||
@@ -289,15 +293,33 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
/** this is ONLY for shared clients */
|
||||
private static I2PSocketManager socketManager;
|
||||
|
||||
/** this is ONLY for shared clients */
|
||||
|
||||
/**
|
||||
* this is ONLY for shared clients
|
||||
* @return non-null
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected synchronized I2PSocketManager getSocketManager() {
|
||||
return getSocketManager(getTunnel(), this.privKeyFile);
|
||||
}
|
||||
/** this is ONLY for shared clients */
|
||||
|
||||
/**
|
||||
* this is ONLY for shared clients
|
||||
* @return non-null
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
|
||||
return getSocketManager(tunnel, null);
|
||||
}
|
||||
/** this is ONLY for shared clients */
|
||||
|
||||
/**
|
||||
* this is ONLY for shared clients
|
||||
* @return non-null
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
|
||||
if (socketManager != null) {
|
||||
I2PSession s = socketManager.getSession();
|
||||
@@ -319,15 +341,43 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
return socketManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-null
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected I2PSocketManager buildSocketManager() {
|
||||
return buildSocketManager(getTunnel(), this.privKeyFile);
|
||||
return buildSocketManager(getTunnel(), this.privKeyFile, this.l);
|
||||
}
|
||||
/**
|
||||
* @return non-null
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
|
||||
return buildSocketManager(tunnel, null);
|
||||
}
|
||||
|
||||
/** @param pkf absolute path or null */
|
||||
private static final int RETRY_DELAY = 20*1000;
|
||||
private static final int MAX_RETRIES = 4;
|
||||
|
||||
/**
|
||||
* @param pkf absolute path or null
|
||||
* @return non-null
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf) {
|
||||
return buildSocketManager(tunnel, pkf, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pkf absolute path or null
|
||||
* @return non-null
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf, Logging log) {
|
||||
Properties props = new Properties();
|
||||
props.putAll(tunnel.getClientOptions());
|
||||
int portNum = 7654;
|
||||
@@ -340,6 +390,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
}
|
||||
|
||||
I2PSocketManager sockManager = null;
|
||||
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
|
||||
int retries = 0;
|
||||
while (sockManager == null) {
|
||||
if (pkf != null) {
|
||||
// Persistent client dest
|
||||
@@ -348,8 +400,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
fis = new FileInputStream(pkf);
|
||||
sockManager = I2PSocketManagerFactory.createManager(fis, tunnel.host, portNum, props);
|
||||
} catch (IOException ioe) {
|
||||
if (log != null)
|
||||
log.log("Error opening key file " + ioe);
|
||||
_log.error("Error opening key file", ioe);
|
||||
// this is going to loop but if we break we'll get a NPE
|
||||
throw new IllegalArgumentException("Error opening key file " + ioe);
|
||||
} finally {
|
||||
if (fis != null)
|
||||
try { fis.close(); } catch (IOException ioe) {}
|
||||
@@ -359,8 +413,22 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
}
|
||||
|
||||
if (sockManager == null) {
|
||||
_log.log(Log.CRIT, "Unable to create socket manager");
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
// try to make this error sensible as it will happen... sadly we can't get to the listenPort, only the listenHost
|
||||
String msg = "Unable to connect to the router at " + tunnel.host + ':' + portNum +
|
||||
" and build tunnels for the client";
|
||||
if (++retries < MAX_RETRIES) {
|
||||
if (log != null)
|
||||
log.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
|
||||
_log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
|
||||
} else {
|
||||
if (log != null)
|
||||
log.log(msg + ", giving up");
|
||||
_log.log(Log.CRIT, msg + ", giving up");
|
||||
// not clear if callers can handle null
|
||||
//return null;
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
sockManager.setName("Client");
|
||||
@@ -479,7 +547,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
localPort = ss.getLocalPort();
|
||||
}
|
||||
notifyEvent("clientLocalPort", new Integer(ss.getLocalPort()));
|
||||
l.log("Listening for clients on port " + localPort + " of " + getTunnel().listenHost);
|
||||
// duplicates message in constructor
|
||||
//l.log("Listening for clients on port " + localPort + " of " + getTunnel().listenHost);
|
||||
|
||||
// Notify constructor that port is ready
|
||||
synchronized (this) {
|
||||
@@ -608,7 +677,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
}
|
||||
} // else the app chaining to this one closes it!
|
||||
}
|
||||
l.log("Closing client " + toString());
|
||||
l.log("Stopping client " + toString());
|
||||
open = false;
|
||||
try {
|
||||
if (ss != null) ss.close();
|
||||
@@ -616,7 +685,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
l.log("Client closed.");
|
||||
//l.log("Client closed.");
|
||||
}
|
||||
|
||||
synchronized (_waitingSockets) { _waitingSockets.notifyAll(); }
|
||||
|
@@ -115,7 +115,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
public I2PTunnelConnectClient(int localPort, Logging l, boolean ownDest,
|
||||
String wwwProxy, EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) throws IllegalArgumentException {
|
||||
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
|
||||
super(localPort, ownDest, l, notifyThis, "HTTPS Proxy on " + tunnel.listenHost + ':' + localPort + " #" + (++__clientId), tunnel);
|
||||
|
||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||
notifyEvent("openConnectClientResult", "error");
|
||||
@@ -128,7 +128,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
_proxyList.add(tok.nextToken().trim());
|
||||
}
|
||||
|
||||
setName(getLocalPort() + " -> ConnectClient [Outproxy list: " + wwwProxy + "]");
|
||||
setName("HTTPS Proxy on " + tunnel.listenHost + ':' + localPort);
|
||||
|
||||
startRunning();
|
||||
}
|
||||
|
@@ -166,7 +166,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
||||
super(localPort, l, sockMgr, tunnel, notifyThis, clientId);
|
||||
// proxyList = new ArrayList();
|
||||
|
||||
setName(getLocalPort() + " -> HTTPClient [NO PROXIES]");
|
||||
setName("HTTP Proxy on " + getTunnel().listenHost + ':' + localPort);
|
||||
startRunning();
|
||||
|
||||
notifyEvent("openHTTPClientResult", "ok");
|
||||
@@ -178,7 +178,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
||||
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest,
|
||||
String wwwProxy, EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) throws IllegalArgumentException {
|
||||
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
|
||||
super(localPort, ownDest, l, notifyThis, "HTTP Proxy on " + tunnel.listenHost + ':' + localPort + " #" + (++__clientId), tunnel);
|
||||
|
||||
//proxyList = new ArrayList(); // We won't use outside of i2p
|
||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||
@@ -192,7 +192,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
||||
_proxyList.add(tok.nextToken().trim());
|
||||
}
|
||||
|
||||
setName(getLocalPort() + " -> HTTPClient [WWW outproxy list: " + wwwProxy + "]");
|
||||
setName("HTTP Proxy on " + tunnel.listenHost + ':' + localPort);
|
||||
|
||||
startRunning();
|
||||
|
||||
|
@@ -46,7 +46,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
ownDest,
|
||||
l,
|
||||
notifyThis,
|
||||
"IRCHandler " + (++__clientId), tunnel, pkf);
|
||||
"IRC Client on " + tunnel.listenHost + ':' + localPort + " #" + (++__clientId), tunnel, pkf);
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(destinations, ", ");
|
||||
dests = new ArrayList(2);
|
||||
@@ -80,7 +80,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
//return;
|
||||
}
|
||||
|
||||
setName(getLocalPort() + " -> IRCClient");
|
||||
setName("IRC Client on " + tunnel.listenHost + ':' + localPort);
|
||||
|
||||
startRunning();
|
||||
|
||||
|
@@ -61,16 +61,24 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
private int DEFAULT_LOCALPORT = 4488;
|
||||
protected int localPort = DEFAULT_LOCALPORT;
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(host + ":" + port + " <- " + privData, notifyThis, tunnel);
|
||||
super("Server at " + host + ':' + port, notifyThis, tunnel);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
|
||||
SetUsePool(tunnel);
|
||||
init(host, port, bais, privData, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
|
||||
EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
|
||||
super("Server at " + host + ':' + port, notifyThis, tunnel);
|
||||
SetUsePool(tunnel);
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
@@ -85,8 +93,12 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
|
||||
super("Server at " + host + ':' + port, notifyThis, tunnel);
|
||||
SetUsePool(tunnel);
|
||||
init(host, port, privData, privkeyname, l);
|
||||
}
|
||||
@@ -100,6 +112,13 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
_usePool = DEFAULT_USE_POOL;
|
||||
}
|
||||
|
||||
private static final int RETRY_DELAY = 20*1000;
|
||||
private static final int MAX_RETRIES = 4;
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
|
||||
* badly that we cant create a socketManager
|
||||
*/
|
||||
private void init(InetAddress host, int port, InputStream privData, String privkeyname, Logging l) {
|
||||
this.l = l;
|
||||
this.remoteHost = host;
|
||||
@@ -111,7 +130,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
try {
|
||||
portNum = Integer.parseInt(getTunnel().port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
_log.log(Log.CRIT, "Invalid port specified [" + getTunnel().port + "], reverting to " + portNum);
|
||||
_log.error("Invalid port specified [" + getTunnel().port + "], reverting to " + portNum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +144,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
|
||||
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
|
||||
int retries = 0;
|
||||
while (sockMgr == null) {
|
||||
synchronized (slock) {
|
||||
sockMgr = I2PSocketManagerFactory.createManager(privDataCopy, getTunnel().host, portNum,
|
||||
@@ -132,15 +152,25 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
|
||||
}
|
||||
if (sockMgr == null) {
|
||||
_log.log(Log.CRIT, "Unable to create socket manager");
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
// try to make this error sensible as it will happen...
|
||||
String msg = "Unable to connect to the router at " + getTunnel().host + ':' + portNum +
|
||||
" and build tunnels for the server at " + getTunnel().listenHost + ':' + port;
|
||||
if (++retries < MAX_RETRIES) {
|
||||
this.l.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
|
||||
_log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
|
||||
} else {
|
||||
this.l.log(msg + ", giving up");
|
||||
_log.log(Log.CRIT, msg + ", giving up");
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {}
|
||||
privDataCopy.reset();
|
||||
}
|
||||
}
|
||||
|
||||
sockMgr.setName("Server");
|
||||
getTunnel().addSession(sockMgr.getSession());
|
||||
l.log("Ready!");
|
||||
l.log("Tunnels ready for server at " + getTunnel().listenHost + ':' + port);
|
||||
notifyEvent("openServerResult", "ok");
|
||||
open = true;
|
||||
}
|
||||
@@ -206,7 +236,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
l.log("Shutting down server " + toString());
|
||||
l.log("Stopping tunnels for server at " + getTunnel().listenHost + ':' + this.remotePort);
|
||||
try {
|
||||
if (i2pss != null) i2pss.close();
|
||||
getTunnel().removeSession(sockMgr.getSession());
|
||||
@@ -215,7 +245,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
_log.error("Error destroying the session", ex);
|
||||
//System.exit(1);
|
||||
}
|
||||
l.log("Server shut down.");
|
||||
//l.log("Server shut down.");
|
||||
open = false;
|
||||
return true;
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ class InternalSocketRunner implements Runnable {
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (this.open) {
|
||||
_log.error("Error listening for internal connections on " + this.port, ex);
|
||||
_log.error("Error listening for internal connections on port " + this.port, ex);
|
||||
}
|
||||
this.open = false;
|
||||
}
|
||||
|
@@ -128,8 +128,8 @@ public class TunnelController implements Logging {
|
||||
try {
|
||||
doStartTunnel();
|
||||
} catch (Exception e) {
|
||||
_log.error("Error starting up the tunnel", e);
|
||||
log("Error starting up the tunnel - " + e.getMessage());
|
||||
_log.error("Error starting the tunnel " + getName(), e);
|
||||
log("Error starting the tunnel " + getName() + ": " + e.getMessage());
|
||||
// if we don't acquire() then the release() in stopTunnel() won't work
|
||||
acquire();
|
||||
stopTunnel();
|
||||
|
@@ -36,7 +36,7 @@ public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel {
|
||||
/** @param pkf private key file name or null for transient key */
|
||||
public I2PSOCKSIRCTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) {
|
||||
super(localPort, l, ownDest, notifyThis, tunnel, pkf);
|
||||
setName(getLocalPort() + " -> SOCKSIRCTunnel");
|
||||
setName("SOCKS IRC Proxy on " + tunnel.listenHost + ':' + localPort);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -36,14 +36,14 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
|
||||
|
||||
/** @param pkf private key file name or null for transient key */
|
||||
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) {
|
||||
super(localPort, ownDest, l, notifyThis, "SOCKSHandler", tunnel, pkf);
|
||||
super(localPort, ownDest, l, notifyThis, "SOCKS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel, pkf);
|
||||
|
||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||
notifyEvent("openSOCKSTunnelResult", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
setName(getLocalPort() + " -> SOCKSTunnel");
|
||||
setName("SOCKS Proxy on " + tunnel.listenHost + ':' + localPort);
|
||||
parseOptions();
|
||||
startRunning();
|
||||
|
||||
|
@@ -90,7 +90,7 @@ public class IndexBean {
|
||||
//static final String PROP_NONCE = IndexBean.class.getName() + ".nonce";
|
||||
//static final String PROP_NONCE_OLD = PROP_NONCE + '2';
|
||||
/** 3 wasn't enough for some browsers. They are reloading the page for some reason - maybe HEAD? @since 0.8.1 */
|
||||
private static final int MAX_NONCES = 5;
|
||||
private static final int MAX_NONCES = 8;
|
||||
/** store nonces in a static FIFO instead of in System Properties @since 0.8.1 */
|
||||
private static final List<String> _nonces = new ArrayList(MAX_NONCES + 1);
|
||||
|
||||
@@ -226,7 +226,7 @@ public class IndexBean {
|
||||
// give the messages a chance to make it to the window
|
||||
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
|
||||
// and give them something to look at in any case
|
||||
return _("Starting tunnel...");
|
||||
return _("Starting tunnel") + ' ' + getTunnelName(_tunnel) + " &hellip";
|
||||
}
|
||||
|
||||
private String stop() {
|
||||
@@ -239,7 +239,7 @@ public class IndexBean {
|
||||
// give the messages a chance to make it to the window
|
||||
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
|
||||
// and give them something to look at in any case
|
||||
return _("Stopping tunnel...");
|
||||
return _("Stopping tunnel") + ' ' + getTunnelName(_tunnel) + " &hellip";
|
||||
}
|
||||
|
||||
private String saveChanges() {
|
||||
|
@@ -29,7 +29,7 @@
|
||||
<div id="pageHeader">
|
||||
</div>
|
||||
|
||||
<form method="post" action="index.jsp">
|
||||
<form method="post" action="list">
|
||||
|
||||
<div id="tunnelEditPanel" class="panel">
|
||||
<div class="header">
|
||||
|
@@ -29,7 +29,7 @@
|
||||
<div id="pageHeader">
|
||||
</div>
|
||||
|
||||
<form method="post" action="index.jsp">
|
||||
<form method="post" action="list">
|
||||
|
||||
<div id="tunnelEditPanel" class="panel">
|
||||
<div class="header">
|
||||
|
@@ -1,2 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>I2P Router Console</title></head>
|
||||
<body><meta http-equiv="refresh" content="0;url=index.jsp" /><a href="index.jsp">Enter</a></body></html>
|
@@ -44,7 +44,7 @@
|
||||
|
||||
<div class="footer">
|
||||
<div class="toolbox">
|
||||
<a class="control" href="index.jsp"><%=intl._("Refresh")%></a>
|
||||
<a class="control" href="list"><%=intl._("Refresh")%></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,7 +53,7 @@
|
||||
<div class="header"></div>
|
||||
<div class="footer">
|
||||
<div class="toolbox">
|
||||
<a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=Stop%20all"><%=intl._("Stop All")%></a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=Start%20all"><%=intl._("Start All")%></a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=Restart%20all"><%=intl._("Restart All")%></a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=Reload%20configuration"><%=intl._("Reload Config")%></a>
|
||||
<a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&action=Stop%20all"><%=intl._("Stop All")%></a> <a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&action=Start%20all"><%=intl._("Start All")%></a> <a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&action=Restart%20all"><%=intl._("Restart All")%></a> <a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&action=Reload%20configuration"><%=intl._("Reload Config")%></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,7 +89,7 @@
|
||||
%>
|
||||
<div class="nameField rowItem">
|
||||
<label><%=intl._("Name")%>:</label>
|
||||
<span class="text"><a href="edit.jsp?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a></span>
|
||||
<span class="text"><a href="edit?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a></span>
|
||||
</div>
|
||||
<div class="previewField rowItem">
|
||||
<label><%=intl._("Points at")%>:</label>
|
||||
@@ -125,17 +125,17 @@
|
||||
switch (indexBean.getTunnelStatus(curServer)) {
|
||||
case IndexBean.STARTING:
|
||||
%><div class="statusStarting text"><%=intl._("Starting...")%></div>
|
||||
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.RUNNING:
|
||||
%><div class="statusRunning text"><%=intl._("Running")%></div>
|
||||
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.NOT_RUNNING:
|
||||
%><div class="statusNotRunning text"><%=intl._("Stopped")%></div>
|
||||
<a class="control" title="Start this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=start&tunnel=<%=curServer%>"><%=intl._("Start")%></a>
|
||||
<a class="control" title="Start this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&action=start&tunnel=<%=curServer%>"><%=intl._("Start")%></a>
|
||||
<%
|
||||
break;
|
||||
}
|
||||
@@ -157,7 +157,7 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<form id="addNewServerTunnelForm" action="edit.jsp">
|
||||
<form id="addNewServerTunnelForm" action="edit">
|
||||
<div class="toolbox">
|
||||
|
||||
<label><%=intl._("New server tunnel")%>:</label>
|
||||
@@ -209,7 +209,7 @@
|
||||
%>
|
||||
<div class="nameField rowItem">
|
||||
<label><%=intl._("Name")%>:</label>
|
||||
<span class="text"><a href="edit.jsp?tunnel=<%=curClient%>" title="Edit Tunnel Settings for <%=indexBean.getTunnelName(curClient)%>"><%=indexBean.getTunnelName(curClient)%></a></span>
|
||||
<span class="text"><a href="edit?tunnel=<%=curClient%>" title="Edit Tunnel Settings for <%=indexBean.getTunnelName(curClient)%>"><%=indexBean.getTunnelName(curClient)%></a></span>
|
||||
</div>
|
||||
<div class="portField rowItem">
|
||||
<label><%=intl._("Port")%>:</label>
|
||||
@@ -229,22 +229,22 @@
|
||||
switch (indexBean.getTunnelStatus(curClient)) {
|
||||
case IndexBean.STARTING:
|
||||
%><div class="statusStarting text"><%=intl._("Starting...")%></div>
|
||||
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.STANDBY:
|
||||
%><div class="statusStarting text"><%=intl._("Standby")%></div>
|
||||
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.RUNNING:
|
||||
%><div class="statusRunning text"><%=intl._("Running")%></div>
|
||||
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
|
||||
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&action=stop&tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
|
||||
<%
|
||||
break;
|
||||
case IndexBean.NOT_RUNNING:
|
||||
%><div class="statusNotRunning text"><%=intl._("Stopped")%></div>
|
||||
<a class="control" title="Start this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&action=start&tunnel=<%=curClient%>"><%=intl._("Start")%></a>
|
||||
<a class="control" title="Start this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&action=start&tunnel=<%=curClient%>"><%=intl._("Start")%></a>
|
||||
<%
|
||||
break;
|
||||
}
|
||||
@@ -285,7 +285,7 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<form id="addNewClientTunnelForm" action="edit.jsp">
|
||||
<form id="addNewClientTunnelForm" action="edit">
|
||||
<div class="toolbox">
|
||||
|
||||
<label><%=intl._("New client tunnel")%>:</label>
|
||||
|
@@ -5,6 +5,19 @@
|
||||
|
||||
<web-app>
|
||||
<!-- precompiled servlets -->
|
||||
|
||||
<!-- yeah we could do this in a handler but this is easier -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>net.i2p.i2ptunnel.jsp.index_jsp</servlet-name>
|
||||
<!-- this becomes the default so it also covers /index and /index.html -->
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>net.i2p.i2ptunnel.jsp.edit_jsp</servlet-name>
|
||||
<url-pattern>/edit</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
|
@@ -22,8 +22,8 @@ public class ConfigNavHelper extends HelperBase {
|
||||
public void renderNavBar(String requestURI) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
for (int i = 0; i < pages.length; i++) {
|
||||
String page = "config" + pages[i] + ".jsp";
|
||||
if (requestURI.indexOf(page) != -1) {
|
||||
String page = "config" + pages[i];
|
||||
if (requestURI.endsWith(page) || requestURI.endsWith(page + ".jsp")) {
|
||||
// we are there
|
||||
buf.append(_(titles[i]));
|
||||
} else {
|
||||
|
@@ -20,7 +20,7 @@ public class ConfigPeerHandler extends FormHandler {
|
||||
} else if (_action.equals(_("Ban peer until restart"))) {
|
||||
Hash h = getHash();
|
||||
if (h != null) {
|
||||
_context.shitlist().shitlistRouterForever(h, _("Manually banned via {0}"), "<a href=\"configpeer.jsp\">configpeer.jsp</a>");
|
||||
_context.shitlist().shitlistRouterForever(h, _("Manually banned via {0}"), "<a href=\"configpeer\">configpeer</a>");
|
||||
addFormNotice(_("Peer") + " " + _peer + " " + _("banned until restart") );
|
||||
return;
|
||||
}
|
||||
|
@@ -81,7 +81,7 @@ public class ConfigRestartBean {
|
||||
|
||||
/** @param s value,label,... pairs */
|
||||
private static void buttons(RouterContext ctx, StringBuilder buf, String url, String nonce, String[] s) {
|
||||
buf.append("<form action=\"").append(url).append("\" method=\"GET\">\n");
|
||||
buf.append("<form action=\"").append(url).append("\" method=\"POST\">\n");
|
||||
buf.append("<input type=\"hidden\" name=\"consoleNonce\" value=\"").append(nonce).append("\" >\n");
|
||||
for (int i = 0; i < s.length; i+= 2)
|
||||
buf.append("<button type=\"submit\" name=\"action\" value=\"").append(s[i]).append("\" >").append(_(s[i+1], ctx)).append("</button>\n");
|
||||
|
@@ -29,7 +29,7 @@ public class ConfigUIHandler extends FormHandler {
|
||||
if (_context.router().saveConfig()) {
|
||||
if (!oldTheme.equals(_config))
|
||||
addFormNotice(_("Theme change saved.") +
|
||||
" <a href=\"configui.jsp\">" +
|
||||
" <a href=\"configui\">" +
|
||||
_("Refresh the page to view.") +
|
||||
"</a>");
|
||||
} else {
|
||||
|
@@ -127,8 +127,8 @@ public class GraphHelper extends HelperBase {
|
||||
public String getForm() {
|
||||
saveSettings();
|
||||
try {
|
||||
_out.write("<br><h3>" + _("Configure Graph Display") + " [<a href=\"configstats.jsp\">" + _("Select Stats") + "</a>]</h3>");
|
||||
_out.write("<form action=\"graphs.jsp\" method=\"GET\">");
|
||||
_out.write("<br><h3>" + _("Configure Graph Display") + " [<a href=\"configstats\">" + _("Select Stats") + "</a>]</h3>");
|
||||
_out.write("<form action=\"graphs\" method=\"POST\">");
|
||||
_out.write(_("Periods") + ": <input size=\"3\" type=\"text\" name=\"periodCount\" value=\"" + _periodCount + "\"><br>\n");
|
||||
_out.write(_("Plot averages") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : "checked=\"true\" ") + "> ");
|
||||
_out.write(_("or")+ " " +_("plot events") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"true\" "+ (_showEvents ? "checked=\"true\" " : "") + "><br>\n");
|
||||
|
@@ -13,7 +13,9 @@ import org.mortbay.jetty.servlet.WebApplicationHandler;
|
||||
/**
|
||||
* Convert foo.jsp to foo_xx.jsp for language xx.
|
||||
* This is appropriate for jsps with large amounts of text.
|
||||
* This does not work for included jsps (e.g. summary*)
|
||||
*
|
||||
* Also, as of 0.8.2, rewrite "/" and "/index.html" to "/index.jsp",x
|
||||
* and "/foo" to "/foo.jsp".
|
||||
*
|
||||
* @author zzz
|
||||
*/
|
||||
@@ -46,9 +48,22 @@ public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
return;
|
||||
}
|
||||
|
||||
// transparent rewriting
|
||||
if (pathInContext.equals("/") || pathInContext.equals("/index.html")) {
|
||||
// home page
|
||||
pathInContext = "/index.jsp";
|
||||
} else if (pathInContext.indexOf("/", 1) < 0 &&
|
||||
!pathInContext.endsWith(".jsp")) {
|
||||
// add .jsp to pages at top level
|
||||
pathInContext += ".jsp";
|
||||
}
|
||||
|
||||
//System.err.println("Path: " + pathInContext);
|
||||
String newPath = pathInContext;
|
||||
if (pathInContext.endsWith(".jsp")) {
|
||||
//if (pathInContext.endsWith(".jsp")) {
|
||||
// We only ended up doing this for help.jsp, so save some effort
|
||||
// unless we translate more pages like this
|
||||
if (pathInContext.equals("/help.jsp")) {
|
||||
int len = pathInContext.length();
|
||||
// ...but leave foo_xx.jsp alone
|
||||
if (len < 8 || pathInContext.charAt(len - 7) != '_') {
|
||||
|
@@ -105,7 +105,7 @@ public class NetDbRenderer {
|
||||
public void renderLeaseSetHTML(Writer out, boolean debug) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(4*1024);
|
||||
buf.append("<h2>" + _("Network Database Contents") + "</h2>\n");
|
||||
buf.append("<a href=\"netdb.jsp\">" + _("View RouterInfo") + "</a>");
|
||||
buf.append("<a href=\"netdb\">" + _("View RouterInfo") + "</a>");
|
||||
buf.append("<h3>").append(_("LeaseSets")).append("</h3>\n");
|
||||
Hash ourRKey;
|
||||
Set<LeaseSet> leases;
|
||||
@@ -130,7 +130,7 @@ public class NetDbRenderer {
|
||||
Hash key = dest.calculateHash();
|
||||
buf.append("<b>").append(_("LeaseSet")).append(": ").append(key.toBase64());
|
||||
if (_context.clientManager().isLocal(dest)) {
|
||||
buf.append(" (<a href=\"tunnels.jsp#" + key.toBase64().substring(0,4) + "\">" + _("Local") + "</a> ");
|
||||
buf.append(" (<a href=\"tunnels#" + key.toBase64().substring(0,4) + "\">" + _("Local") + "</a> ");
|
||||
if (! _context.clientManager().shouldPublishLeaseSet(key))
|
||||
buf.append(_("Unpublished") + ' ');
|
||||
buf.append(_("Destination") + ' ');
|
||||
@@ -212,7 +212,7 @@ public class NetDbRenderer {
|
||||
* @param mode 0: our info and charts only; 1: full routerinfos and charts; 2: abbreviated routerinfos and charts
|
||||
*/
|
||||
public void renderStatusHTML(Writer out, int mode) throws IOException {
|
||||
out.write("<h2>" + _("Network Database Contents") + " (<a href=\"netdb.jsp?l=1\">" + _("View LeaseSets") + "</a>)</h2>\n");
|
||||
out.write("<h2>" + _("Network Database Contents") + " (<a href=\"netdb?l=1\">" + _("View LeaseSets") + "</a>)</h2>\n");
|
||||
if (!_context.netDb().isInitialized()) {
|
||||
out.write(_("Not initialized"));
|
||||
out.flush();
|
||||
@@ -223,7 +223,7 @@ public class NetDbRenderer {
|
||||
boolean shortStats = mode == 2;
|
||||
boolean showStats = full || shortStats;
|
||||
Hash us = _context.routerHash();
|
||||
out.write("<a name=\"routers\" ></a><h3>" + _("Routers") + " (<a href=\"netdb.jsp");
|
||||
out.write("<a name=\"routers\" ></a><h3>" + _("Routers") + " (<a href=\"netdb");
|
||||
if (full || !showStats)
|
||||
out.write("?f=2#routers\" >" + _("Show all routers"));
|
||||
else
|
||||
@@ -343,9 +343,9 @@ public class NetDbRenderer {
|
||||
} else {
|
||||
buf.append("<b>" + _("Peer info for") + ":</b> ").append(hash).append("\n");
|
||||
if (full) {
|
||||
buf.append("[<a href=\"netdb.jsp\" >Back</a>]</th></tr><td>\n");
|
||||
buf.append("[<a href=\"netdb\" >Back</a>]</th></tr><td>\n");
|
||||
} else {
|
||||
buf.append("[<a href=\"netdb.jsp?r=").append(hash.substring(0, 6)).append("\" >").append(_("Full entry")).append("</a>]</th></tr><td>\n");
|
||||
buf.append("[<a href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >").append(_("Full entry")).append("</a>]</th></tr><td>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -49,25 +49,36 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
private static final String TEMP_NEWS_FILE = "news.xml.temp";
|
||||
/** @since 0.7.14 not configurable */
|
||||
private static final String BACKUP_NEWS_URL = "http://www.i2p2.i2p/_static/news/news.xml";
|
||||
private static final String PROP_LAST_CHECKED = "router.newsLastChecked";
|
||||
|
||||
private NewsFetcher(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(NewsFetcher.class);
|
||||
_instance = this;
|
||||
_lastFetch = 0;
|
||||
try {
|
||||
String last = ctx.getProperty(PROP_LAST_CHECKED);
|
||||
if (last != null)
|
||||
_lastFetch = Long.parseLong(last);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
_newsFile = new File(_context.getRouterDir(), NEWS_FILE);
|
||||
_tempFile = new File(_context.getTempDir(), TEMP_NEWS_FILE);
|
||||
updateLastFetched();
|
||||
_lastUpdated = _lastFetch;
|
||||
_updateVersion = "";
|
||||
}
|
||||
|
||||
private void updateLastFetched() {
|
||||
if (_newsFile.exists()) {
|
||||
if (_lastUpdated == 0)
|
||||
_lastUpdated = _newsFile.lastModified();
|
||||
if (_lastFetch == 0)
|
||||
_lastFetch = _newsFile.lastModified();
|
||||
} else
|
||||
_lastFetch = _lastUpdated;
|
||||
if (_lastModified == null)
|
||||
_lastModified = to822Date(_lastFetch);
|
||||
} else {
|
||||
_lastUpdated = 0;
|
||||
_lastFetch = 0;
|
||||
_lastModified = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateAvailable() { return _updateAvailable; }
|
||||
@@ -136,7 +147,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
return true;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Last fetched " + DataHelper.formatDuration2(_context.clock().now() - _lastFetch) + " ago");
|
||||
_log.debug("Last fetched " + DataHelper.formatDuration(_context.clock().now() - _lastFetch) + " ago");
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
@@ -273,6 +284,11 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** @since 0.8.2 */
|
||||
private static String to822Date(long t) {
|
||||
return (new SimpleDateFormat("d MMM yyyy HH:mm:ss z", Locale.US)).format(new Date(t));
|
||||
}
|
||||
|
||||
private static final String VERSION_STRING = "version=\"" + RouterVersion.VERSION + "\"";
|
||||
private static final String VERSION_PREFIX = "version=\"";
|
||||
private void checkForUpdates() {
|
||||
@@ -374,6 +390,10 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
_log.warn("Transfer complete, but no file? - probably 304 Not Modified");
|
||||
}
|
||||
_lastFetch = now;
|
||||
if (_context.isRouterContext()) {
|
||||
((RouterContext)_context).router().setConfigSetting(PROP_LAST_CHECKED, "" + now);
|
||||
((RouterContext)_context).router().saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
|
||||
|
@@ -74,7 +74,7 @@ class ProfileOrganizerRenderer {
|
||||
if (older > 0)
|
||||
buf.append(_("Hiding {0} older profiles.", older)).append('\n');
|
||||
if (standard > 0)
|
||||
buf.append("<a href=\"/profiles.jsp?f=1\">").append(_("Hiding {0} standard profiles.", standard)).append("</a>\n");
|
||||
buf.append("<a href=\"/profiles?f=1\">").append(_("Hiding {0} standard profiles.", standard)).append("</a>\n");
|
||||
buf.append("</p>");
|
||||
buf.append("<table>");
|
||||
buf.append("<tr>");
|
||||
@@ -173,7 +173,7 @@ class ProfileOrganizerRenderer {
|
||||
buf.append(" </td>");
|
||||
buf.append("<td nowrap align=\"center\"><a target=\"_blank\" href=\"dumpprofile.jsp?peer=")
|
||||
.append(peer.toBase64().substring(0,6)).append("\">").append(_("profile")).append("</a>");
|
||||
buf.append(" <a href=\"configpeer.jsp?peer=").append(peer.toBase64()).append("\">+-</a></td>\n");
|
||||
buf.append(" <a href=\"configpeer?peer=").append(peer.toBase64()).append("\">+-</a></td>\n");
|
||||
buf.append("</tr>");
|
||||
// let's not build the whole page in memory (~500 bytes per peer)
|
||||
out.write(buf.toString());
|
||||
|
@@ -67,7 +67,7 @@ public class ShitlistRenderer {
|
||||
else
|
||||
buf.append(_(entry.cause));
|
||||
}
|
||||
buf.append(" (<a href=\"configpeer.jsp?peer=").append(key.toBase64())
|
||||
buf.append(" (<a href=\"configpeer?peer=").append(key.toBase64())
|
||||
.append("#unsh\">").append(_("unban now")).append("</a>)");
|
||||
buf.append("</li>\n");
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ public class StatsGenerator {
|
||||
|
||||
public void generateStatsPage(Writer out, boolean showAll) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(16*1024);
|
||||
buf.append("<div class=\"joblog\"><form action=\"/stats.jsp\">");
|
||||
buf.append("<div class=\"joblog\"><form action=\"\">");
|
||||
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
@@ -39,7 +39,7 @@ public class StatsGenerator {
|
||||
for (Iterator iter = groups.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String group = (String)entry.getKey();
|
||||
buf.append("<option value=\"/stats.jsp#").append(group).append("\">");
|
||||
buf.append("<option value=\"#").append(group).append("\">");
|
||||
buf.append(_(group)).append("</option>\n");
|
||||
// let's just do the groups
|
||||
//Set stats = (Set)entry.getValue();
|
||||
|
@@ -28,7 +28,7 @@ public class SummaryBarRenderer {
|
||||
StringBuilder buf = new StringBuilder(8*1024);
|
||||
String theme = _context.getProperty(CSSHelper.PROP_THEME_NAME, CSSHelper.DEFAULT_THEME);
|
||||
|
||||
buf.append("<a href=\"/index.jsp\" target=\"_top\"><img src=\"")
|
||||
buf.append("<a href=\"/\" target=\"_top\"><img src=\"")
|
||||
.append(CSSHelper.BASE_THEME_PATH)
|
||||
.append(theme)
|
||||
.append("/images/i2plogo.png\" alt=\"")
|
||||
@@ -37,7 +37,7 @@ public class SummaryBarRenderer {
|
||||
.append(_("I2P Router Console"))
|
||||
.append("\"></a><hr>")
|
||||
|
||||
.append("<h3><a href=\"/help.jsp\" target=\"_top\" title=\"")
|
||||
.append("<h3><a href=\"/help\" target=\"_top\" title=\"")
|
||||
.append(_("I2P Router Help & FAQ"))
|
||||
.append("\">")
|
||||
.append(_("Help & FAQ"))
|
||||
@@ -51,7 +51,7 @@ public class SummaryBarRenderer {
|
||||
linkhelper.setMaxLines("100");
|
||||
buf.append(linkhelper.getContent());
|
||||
} else {
|
||||
buf.append("<h3><a href=\"/configclients.jsp\" target=\"_top\" title=\"")
|
||||
buf.append("<h3><a href=\"/configclients\" target=\"_top\" title=\"")
|
||||
.append(_("Configure startup of clients and webapps (services); manually start dormant services"))
|
||||
.append("\">")
|
||||
.append(_("I2P Services"))
|
||||
@@ -87,7 +87,7 @@ public class SummaryBarRenderer {
|
||||
|
||||
.append("</td></tr></table>\n" +
|
||||
|
||||
"<hr><h3><a href=\"/config.jsp\" target=\"_top\" title=\"")
|
||||
"<hr><h3><a href=\"/config\" target=\"_top\" title=\"")
|
||||
.append(_("Configure I2P Router"))
|
||||
.append("\">")
|
||||
.append(_("I2P Internals"))
|
||||
@@ -95,31 +95,31 @@ public class SummaryBarRenderer {
|
||||
|
||||
"<table><tr><td>\n" +
|
||||
|
||||
"<a href=\"/tunnels.jsp\" target=\"_top\" title=\"")
|
||||
"<a href=\"/tunnels\" target=\"_top\" title=\"")
|
||||
.append(_("View existing tunnels and tunnel build status"))
|
||||
.append("\">")
|
||||
.append(_("Tunnels"))
|
||||
.append("</a>\n" +
|
||||
|
||||
"<a href=\"/peers.jsp\" target=\"_top\" title=\"")
|
||||
"<a href=\"/peers\" target=\"_top\" title=\"")
|
||||
.append(_("Show all current peer connections"))
|
||||
.append("\">")
|
||||
.append(_("Peers"))
|
||||
.append("</a>\n" +
|
||||
|
||||
"<a href=\"/profiles.jsp\" target=\"_top\" title=\"")
|
||||
"<a href=\"/profiles\" target=\"_top\" title=\"")
|
||||
.append(_("Show recent peer performance profiles"))
|
||||
.append("\">")
|
||||
.append(_("Profiles"))
|
||||
.append("</a>\n" +
|
||||
|
||||
"<a href=\"/netdb.jsp\" target=\"_top\" title=\"")
|
||||
"<a href=\"/netdb\" target=\"_top\" title=\"")
|
||||
.append(_("Show list of all known I2P routers"))
|
||||
.append("\">")
|
||||
.append(_("NetDB"))
|
||||
.append("</a>\n" +
|
||||
|
||||
"<a href=\"/logs.jsp\" target=\"_top\" title=\"")
|
||||
"<a href=\"/logs\" target=\"_top\" title=\"")
|
||||
.append(_("Health Report"))
|
||||
.append("\">")
|
||||
.append(_("Logs"))
|
||||
@@ -131,19 +131,19 @@ public class SummaryBarRenderer {
|
||||
// .append(_("Jobs"))
|
||||
// .append("</a>\n" +
|
||||
|
||||
"<a href=\"/graphs.jsp\" target=\"_top\" title=\"")
|
||||
"<a href=\"/graphs\" target=\"_top\" title=\"")
|
||||
.append(_("Graph router performance"))
|
||||
.append("\">")
|
||||
.append(_("Graphs"))
|
||||
.append("</a>\n" +
|
||||
|
||||
"<a href=\"/stats.jsp\" target=\"_top\" title=\"")
|
||||
"<a href=\"/stats\" target=\"_top\" title=\"")
|
||||
.append(_("Textual router performance statistics"))
|
||||
.append("\">")
|
||||
.append(_("Stats"))
|
||||
.append("</a>\n" +
|
||||
|
||||
"<a href=\"/i2ptunnel/index.jsp\" target=\"_blank\" title=\"")
|
||||
"<a href=\"/i2ptunnel/\" target=\"_blank\" title=\"")
|
||||
.append(_("Local Destinations"))
|
||||
.append("\">")
|
||||
.append(_("I2PTunnel"))
|
||||
@@ -156,7 +156,7 @@ public class SummaryBarRenderer {
|
||||
|
||||
|
||||
|
||||
buf.append("<hr><h3><a href=\"/help.jsp\" target=\"_top\" title=\"")
|
||||
buf.append("<hr><h3><a href=\"/help\" target=\"_top\" title=\"")
|
||||
.append(_("I2P Router Help"))
|
||||
.append("\">")
|
||||
.append(_("General"))
|
||||
@@ -173,7 +173,7 @@ public class SummaryBarRenderer {
|
||||
.append(_helper.getIdent())
|
||||
.append(", ")
|
||||
.append(_("never reveal it to anyone"))
|
||||
.append("\" href=\"/netdb.jsp?r=.\" target=\"_top\">")
|
||||
.append("\" href=\"/netdb?r=.\" target=\"_top\">")
|
||||
.append(_("show"))
|
||||
.append("</a></td></tr>\n" +
|
||||
|
||||
@@ -194,7 +194,7 @@ public class SummaryBarRenderer {
|
||||
.append(_helper.getUptime())
|
||||
.append("</td></tr></table>\n" +
|
||||
|
||||
"<hr><h4><a href=\"/config.jsp#help\" target=\"_top\" title=\"")
|
||||
"<hr><h4><a href=\"/config#help\" target=\"_top\" title=\"")
|
||||
.append(_("Help with configuring your firewall and router for optimal I2P performance"))
|
||||
.append("\">")
|
||||
.append(_("Network"))
|
||||
@@ -220,7 +220,7 @@ public class SummaryBarRenderer {
|
||||
System.setProperty("net.i2p.router.web.UpdateHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.UpdateHandler.nonce", nonce+"");
|
||||
String uri = _helper.getRequestURI();
|
||||
buf.append("<p><form action=\"").append(uri).append("\" method=\"GET\">\n");
|
||||
buf.append("<p><form action=\"").append(uri).append("\" method=\"POST\">\n");
|
||||
buf.append("<input type=\"hidden\" name=\"updateNonce\" value=\"").append(nonce).append("\" >\n");
|
||||
if (_helper.updateAvailable()) {
|
||||
buf.append("<button type=\"submit\" name=\"updateAction\" value=\"signed\" >")
|
||||
@@ -250,7 +250,7 @@ public class SummaryBarRenderer {
|
||||
buf.append("<p>")
|
||||
.append(ConfigRestartBean.renderStatus(_helper.getRequestURI(), _helper.getAction(), _helper.getConsoleNonce()))
|
||||
|
||||
.append("</p><hr><h3><a href=\"/peers.jsp\" target=\"_top\" title=\"")
|
||||
.append("</p><hr><h3><a href=\"/peers\" target=\"_top\" title=\"")
|
||||
.append(_("Show all current peer connections"))
|
||||
.append("\">")
|
||||
.append(_("Peers"))
|
||||
@@ -260,10 +260,11 @@ public class SummaryBarRenderer {
|
||||
|
||||
"<tr><td align=\"left\"><b>")
|
||||
.append(_("Active"))
|
||||
.append(":</b></td><td align=\"right\">")
|
||||
.append(_helper.getActivePeers())
|
||||
.append(":</b></td><td align=\"right\">");
|
||||
int active = _helper.getActivePeers();
|
||||
buf.append(active)
|
||||
.append(" / ")
|
||||
.append(_helper.getActiveProfiles())
|
||||
.append(Math.max(active, _helper.getActiveProfiles()))
|
||||
.append("</td></tr>\n" +
|
||||
|
||||
"<tr><td align=\"left\"><b>")
|
||||
@@ -299,7 +300,7 @@ public class SummaryBarRenderer {
|
||||
|
||||
boolean anotherLine = false;
|
||||
if (_helper.showFirewallWarning()) {
|
||||
buf.append("<h4><a href=\"/config.jsp\" target=\"_top\" title=\"")
|
||||
buf.append("<h4><a href=\"/config\" target=\"_top\" title=\"")
|
||||
.append(_("Help with firewall configuration"))
|
||||
.append("\">")
|
||||
.append(_("Check NAT/firewall"))
|
||||
@@ -320,7 +321,7 @@ public class SummaryBarRenderer {
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+"");
|
||||
String uri = _helper.getRequestURI();
|
||||
buf.append("<p><form action=\"").append(uri).append("\" method=\"GET\">\n");
|
||||
buf.append("<p><form action=\"").append(uri).append("\" method=\"POST\">\n");
|
||||
buf.append("<input type=\"hidden\" name=\"reseedNonce\" value=\"").append(nonce).append("\" >\n");
|
||||
buf.append("<button type=\"submit\" value=\"Reseed\" >").append(_("Reseed")).append("</button></form></p>\n");
|
||||
}
|
||||
@@ -338,7 +339,7 @@ public class SummaryBarRenderer {
|
||||
buf.append("<hr>");
|
||||
|
||||
|
||||
buf.append("<h3><a href=\"/config.jsp\" title=\"")
|
||||
buf.append("<h3><a href=\"/config\" title=\"")
|
||||
.append(_("Configure router bandwidth allocation"))
|
||||
.append("\" target=\"_top\">")
|
||||
.append(_("Bandwidth in/out"))
|
||||
@@ -375,7 +376,7 @@ public class SummaryBarRenderer {
|
||||
.append(_helper.getOutboundTransferred())
|
||||
.append("</td></tr></table>\n" +
|
||||
|
||||
"<hr><h3><a href=\"/tunnels.jsp\" target=\"_top\" title=\"")
|
||||
"<hr><h3><a href=\"/tunnels\" target=\"_top\" title=\"")
|
||||
.append(_("View existing tunnels and tunnel build status"))
|
||||
.append("\">")
|
||||
.append(_("Tunnels"))
|
||||
@@ -406,7 +407,7 @@ public class SummaryBarRenderer {
|
||||
.append(_helper.getShareRatio())
|
||||
.append("</td></tr>\n" +
|
||||
|
||||
"</table><hr><h3><a href=\"/jobs.jsp\" target=\"_top\" title=\"")
|
||||
"</table><hr><h3><a href=\"/jobs\" target=\"_top\" title=\"")
|
||||
.append(_("What's in the router's job queue?"))
|
||||
.append("\">")
|
||||
.append(_("Congestion"))
|
||||
|
@@ -362,7 +362,7 @@ public class SummaryHelper extends HelperBase {
|
||||
List<Destination> clients = new ArrayList(_context.clientManager().listClients());
|
||||
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
buf.append("<h3><a href=\"/i2ptunnel/index.jsp\" target=\"_blank\" title=\"").append(_("Add/remove/edit & control your client and server tunnels")).append("\">").append(_("Local Destinations")).append("</a></h3><hr><div class=\"tunnels\">");
|
||||
buf.append("<h3><a href=\"/i2ptunnel/\" target=\"_blank\" title=\"").append(_("Add/remove/edit & control your client and server tunnels")).append("\">").append(_("Local Destinations")).append("</a></h3><hr><div class=\"tunnels\">");
|
||||
if (!clients.isEmpty()) {
|
||||
Collections.sort(clients, new AlphaComparator());
|
||||
buf.append("<table>");
|
||||
@@ -377,7 +377,7 @@ public class SummaryHelper extends HelperBase {
|
||||
buf.append("server.png\" alt=\"Server\" title=\"" + _("Server") + "\">");
|
||||
else
|
||||
buf.append("client.png\" alt=\"Client\" title=\"" + _("Client") + "\">");
|
||||
buf.append("</td><td align=\"left\"><b><a href=\"tunnels.jsp#").append(h.toBase64().substring(0,4));
|
||||
buf.append("</td><td align=\"left\"><b><a href=\"tunnels#").append(h.toBase64().substring(0,4));
|
||||
buf.append("\" target=\"_top\" title=\"" + _("Show tunnels") + "\">");
|
||||
if (name.length() < 16)
|
||||
buf.append(name);
|
||||
|
@@ -38,7 +38,7 @@ public class TunnelRenderer {
|
||||
}
|
||||
|
||||
public void renderStatusHTML(Writer out) throws IOException {
|
||||
out.write("<div class=\"wideload\"><h2><a name=\"exploratory\" ></a>" + _("Exploratory tunnels") + " (<a href=\"/configtunnels.jsp#exploratory\">" + _("configure") + "</a>)</h2>\n");
|
||||
out.write("<div class=\"wideload\"><h2><a name=\"exploratory\" ></a>" + _("Exploratory tunnels") + " (<a href=\"/configtunnels#exploratory\">" + _("configure") + "</a>)</h2>\n");
|
||||
renderPool(out, _context.tunnelManager().getInboundExploratoryPool(), _context.tunnelManager().getOutboundExploratoryPool());
|
||||
|
||||
List<Hash> destinations = null;
|
||||
@@ -60,7 +60,7 @@ public class TunnelRenderer {
|
||||
out.write("<h2><a name=\"" + client.toBase64().substring(0,4)
|
||||
+ "\" ></a>" + _("Client tunnels for") + ' ' + _(name));
|
||||
if (_context.clientManager().isLocal(client))
|
||||
out.write(" (<a href=\"/configtunnels.jsp#" + client.toBase64().substring(0,4) +"\">" + _("configure") + "</a>)</h2>\n");
|
||||
out.write(" (<a href=\"/configtunnels#" + client.toBase64().substring(0,4) +"\">" + _("configure") + "</a>)</h2>\n");
|
||||
else
|
||||
out.write(" (" + _("dead") + ")</h2>\n");
|
||||
renderPool(out, in, outPool);
|
||||
|
@@ -20,7 +20,7 @@
|
||||
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="formhandler" property="allMessages" />
|
||||
<div class="configure">
|
||||
<form action="config.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigNetHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigNetHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigNetHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
@@ -96,7 +96,7 @@
|
||||
<a href="#chelp"><%=intl._("There is help below.")%></a></b>
|
||||
</p><p><b><%=intl._("UPnP Configuration")%>:</b><br>
|
||||
<input type="checkbox" class="optbox" name="upnp" value="true" <jsp:getProperty name="nethelper" property="upnpChecked" /> >
|
||||
<%=intl._("Enable UPnP to open firewall ports")%> - <a href="peers.jsp#upnp"><%=intl._("UPnP status")%></a>
|
||||
<%=intl._("Enable UPnP to open firewall ports")%> - <a href="peers#upnp"><%=intl._("UPnP status")%></a>
|
||||
</p><p><b><%=intl._("IP Configuration")%>:</b><br>
|
||||
<%=intl._("Externally reachable hostname or IP address")%>:<br>
|
||||
<input type="radio" class="optbox" name="udpAutoIP" value="local,upnp,ssu" <%=nethelper.getUdpAutoIPChecked(3) %> >
|
||||
@@ -196,7 +196,7 @@
|
||||
<li class="tidylist"><%=intl._("Multiple firewall/routers in the internet connection path")%>
|
||||
<li class="tidylist"><%=intl._("UPnP device change, reset, or address change")%>
|
||||
</ul></p><p>
|
||||
<a href="peers.jsp#upnp"><%=intl._("Review the UPnP status here.")%></a>
|
||||
<a href="peers#upnp"><%=intl._("Review the UPnP status here.")%></a>
|
||||
<%=intl._("UPnP may be enabled or disabled above, but a change requires a router restart to take effect.")%></p>
|
||||
<p><%=intl._("Hostnames entered above will be published in the network database.")%>
|
||||
<%=intl._("They are <b>not private</b>.")%>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<jsp:getProperty name="formhandler" property="allMessages" />
|
||||
<div class="configure">
|
||||
<div class="wideload">
|
||||
<form action="configadvanced.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigAdvancedHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigAdvancedHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigAdvancedHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
|
@@ -26,7 +26,7 @@ button span.hide{
|
||||
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
|
||||
<jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
|
||||
<jsp:getProperty name="formhandler" property="allMessages" />
|
||||
<div class="configure"><form action="configclients.jsp" method="POST">
|
||||
<div class="configure"><form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigClientsHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigClientsHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigClientsHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
|
@@ -25,14 +25,14 @@
|
||||
<jsp:getProperty name="keyringhelper" property="summary" />
|
||||
</p></div>
|
||||
|
||||
<form action="configkeyring.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigKeyringHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigKeyringHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigKeyringHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigKeyringHandler.nonce")%>" >
|
||||
<h3><%=intl._("Manual Keyring Addition")%></h3><p>
|
||||
<%=intl._("Enter keys for encrypted remote destinations here.")%>
|
||||
<%=intl._("Keys for local destinations must be entered on the")%> <a href="i2ptunnel/index.jsp"><%=intl._("I2PTunnel page")%></a>.
|
||||
<%=intl._("Keys for local destinations must be entered on the")%> <a href="i2ptunnel/"><%=intl._("I2PTunnel page")%></a>.
|
||||
</p>
|
||||
<div class="wideload">
|
||||
<p><table><tr>
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="formhandler" property="allMessages" />
|
||||
<div class="configure">
|
||||
<form action="configlogging.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigLoggingHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigLoggingHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigLoggingHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
|
@@ -27,7 +27,7 @@
|
||||
peer = net.i2p.data.DataHelper.stripHTML(request.getParameter("peer")); // XSS
|
||||
%>
|
||||
<div class="configure">
|
||||
<form action="configpeer.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigPeerHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigPeerHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigPeerHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
@@ -49,7 +49,7 @@
|
||||
</div>
|
||||
|
||||
<h3><%=intl._("Adjust Profile Bonuses")%></h3>
|
||||
<p><%=intl._("Bonuses may be positive or negative, and affect the peer's inclusion in Fast and High Capacity tiers. Fast peers are used for client tunnels, and High Capacity peers are used for some exploratory tunnels. Current bonuses are displayed on the")%> <a href="profiles.jsp"><%=intl._("profiles page")%></a>.</p>
|
||||
<p><%=intl._("Bonuses may be positive or negative, and affect the peer's inclusion in Fast and High Capacity tiers. Fast peers are used for client tunnels, and High Capacity peers are used for some exploratory tunnels. Current bonuses are displayed on the")%> <a href="profiles"><%=intl._("profiles page")%></a>.</p>
|
||||
<% long speed = 0; long capacity = 0;
|
||||
if (! "".equals(peer)) {
|
||||
// get existing bonus values?
|
||||
|
@@ -17,7 +17,7 @@
|
||||
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="formhandler" property="allMessages" />
|
||||
<div class="configure">
|
||||
<form action="configservice.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigServiceHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigServiceHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigServiceHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
@@ -60,7 +60,7 @@
|
||||
<% } %>
|
||||
|
||||
<h3><%=intl._("Debugging")%></h3>
|
||||
<p><a href="/jobs.jsp"><%=intl._("View the job queue")%></a>
|
||||
<p><a href="/jobs"><%=intl._("View the job queue")%></a>
|
||||
<% if (System.getProperty("wrapper.version") != null) { %>
|
||||
<p><%=intl._("At times, it may be helpful to debug I2P by getting a thread dump. To do so, please select the following option and review the thread dumped to <a href=\"logs.jsp#servicelogs\">wrapper.log</a>.")%></p>
|
||||
<hr><div class="formaction">
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
<h3><%=intl._("Launch browser on router startup?")%></h3>
|
||||
<p><%=intl._("I2P's main configuration interface is this web console, so for your convenience I2P can launch a web browser on startup pointing at")%>
|
||||
<a href="http://127.0.0.1:7657/index.jsp">http://127.0.0.1:7657/index.jsp</a> .</p>
|
||||
<a href="http://127.0.0.1:7657/">http://127.0.0.1:7657/</a> .</p>
|
||||
<hr><div class="formaction">
|
||||
<input type="submit" name="action" value="<%=intl._("View console on startup")%>" >
|
||||
<input type="submit" name="action" value="<%=intl._("Do not view console on startup")%>" >
|
||||
|
@@ -65,7 +65,7 @@ function toggleAll(category)
|
||||
<jsp:useBean class="net.i2p.router.web.ConfigStatsHelper" id="statshelper" scope="request" />
|
||||
<jsp:setProperty name="statshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<div class="configure">
|
||||
<form id="statsForm" name="statsForm" action="configstats.jsp" method="POST">
|
||||
<form id="statsForm" name="statsForm" action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigStatsHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigStatsHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigStatsHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
|
@@ -29,7 +29,7 @@
|
||||
<%=intl._("High CPU and/or high outbound bandwidth usage may result.")%>
|
||||
<%=intl._("Change these settings with care, and adjust them if you have problems.")%>
|
||||
<div class="wideload">
|
||||
<form action="configtunnels.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigTunnelsHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigTunnelsHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigTunnelsHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
|
@@ -22,7 +22,7 @@
|
||||
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="formhandler" property="allMessages" />
|
||||
<div class="configure"><div class="topshimten"><h3><%=uihelper._("Router Console Theme")%></h3></div>
|
||||
<form action="configui.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigUIHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigUIHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigUIHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
|
@@ -21,7 +21,7 @@
|
||||
<div class="messages">
|
||||
<i><jsp:getProperty name="updatehelper" property="newsStatus" /></i></div>
|
||||
<div class="configure">
|
||||
<form action="configupdate.jsp" method="POST">
|
||||
<form action="" method="POST">
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigUpdateHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigUpdateHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigUpdateHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
|
@@ -1,2 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>I2P Router Console</title></head>
|
||||
<body><meta http-equiv="refresh" content="0;url=index.jsp" /><a href="index.jsp">Enter</a></body></html>
|
@@ -24,7 +24,7 @@
|
||||
} else {
|
||||
// since we don't have an iframe this will reload the base page, and
|
||||
// the new delay will be passed to the iframe above
|
||||
out.print("<div class=\"refresh\"><form action=\"" + request.getRequestURI() + "\" method=\"GET\">\n");
|
||||
out.print("<div class=\"refresh\"><form action=\"" + request.getRequestURI() + "\" method=\"POST\">\n");
|
||||
out.print("<b>");
|
||||
// We have intl defined when this is included, but not when compiled standalone.
|
||||
out.print(intl._("Refresh (s)"));
|
||||
|
@@ -52,7 +52,7 @@
|
||||
<%
|
||||
// d and shutdownSoon defined above
|
||||
if (!shutdownSoon) {
|
||||
out.print("<div class=\"refresh\"><form action=\"summaryframe.jsp\" method=\"GET\">\n");
|
||||
out.print("<div class=\"refresh\"><form action=\"summaryframe.jsp\" method=\"POST\">\n");
|
||||
if ("0".equals(d)) {
|
||||
out.print("<b>");
|
||||
out.print(intl._("Refresh (s)"));
|
||||
|
@@ -158,6 +158,7 @@
|
||||
<ant dir="apps/susidns/src/" target="poupdate" />
|
||||
</target>
|
||||
<target name="javadoc">
|
||||
<ant dir="apps/jetty" target="ensureJettylib" />
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/javadoc" />
|
||||
<!-- get release and build version numbers -->
|
||||
@@ -581,8 +582,10 @@
|
||||
<exec executable="echo" osfamily="unix" failifexecutionfails="true" output="pkg-temp/history.txt" append="true">
|
||||
<arg value="EARLIER HISTORY IS AVAILABLE IN THE SOURCE PACKAGE" />
|
||||
</exec>
|
||||
<!-- may be pointless now, people with split directories will never see this -->
|
||||
<!-- May be pointless now, people with split directories will never see this,
|
||||
and for flat installs we don't want to overwrite news more recent than the update package.
|
||||
<copy file="installer/resources/news.xml" todir="pkg-temp/docs/" />
|
||||
-->
|
||||
</target>
|
||||
<target name="prepupdateSmall" depends="buildSmall, prepupdateRouter, prepthemeupdates">
|
||||
<copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
|
||||
|
@@ -114,6 +114,11 @@ public class I2PAppContext {
|
||||
*
|
||||
*/
|
||||
public static I2PAppContext getGlobalContext() {
|
||||
// skip the global lock
|
||||
I2PAppContext rv = _globalAppContext;
|
||||
if (rv != null)
|
||||
return rv;
|
||||
|
||||
synchronized (I2PAppContext.class) {
|
||||
if (_globalAppContext == null) {
|
||||
_globalAppContext = new I2PAppContext(false, null);
|
||||
@@ -122,6 +127,18 @@ public class I2PAppContext {
|
||||
return _globalAppContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the default context, WITHOUT creating a new one.
|
||||
* Use this in static methods used early in router initialization,
|
||||
* where creating a context messes things up.
|
||||
*
|
||||
* @return context or null
|
||||
* @since 0.8.2
|
||||
*/
|
||||
public static I2PAppContext getCurrentContext() {
|
||||
return _globalAppContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets root a brand new context
|
||||
*
|
||||
@@ -257,6 +274,7 @@ public class I2PAppContext {
|
||||
_appDir = _routerDir;
|
||||
}
|
||||
/******
|
||||
(new Exception("Initialized by")).printStackTrace();
|
||||
System.err.println("Base directory: " + _baseDir.getAbsolutePath());
|
||||
System.err.println("Config directory: " + _configDir.getAbsolutePath());
|
||||
System.err.println("Router directory: " + _routerDir.getAbsolutePath());
|
||||
|
@@ -15,39 +15,28 @@ import java.io.PrintWriter;
|
||||
/**
|
||||
* Base class of I2P exceptions
|
||||
*
|
||||
* This was originally used to provide chained exceptions, but
|
||||
* those were added to Exception in Java 1.4, so this class provides nothing
|
||||
* extra at the moment.
|
||||
*
|
||||
* @author jrandom
|
||||
*/
|
||||
public class I2PException extends Exception {
|
||||
private Throwable _source;
|
||||
|
||||
public I2PException() {
|
||||
this(null, null);
|
||||
super();
|
||||
}
|
||||
|
||||
public I2PException(String msg) {
|
||||
this(msg, null);
|
||||
}
|
||||
|
||||
public I2PException(String msg, Throwable source) {
|
||||
super(msg);
|
||||
_source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace() {
|
||||
if (_source != null) _source.printStackTrace();
|
||||
super.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintStream ps) {
|
||||
if (_source != null) _source.printStackTrace(ps);
|
||||
super.printStackTrace(ps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintWriter pw) {
|
||||
if (_source != null) _source.printStackTrace(pw);
|
||||
super.printStackTrace(pw);
|
||||
public I2PException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 0.8.2 */
|
||||
public I2PException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
@@ -304,7 +304,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
|
||||
while (!_dateReceived) {
|
||||
if (waitcount++ > 30) {
|
||||
closeSocket();
|
||||
throw new IOException("no date handshake");
|
||||
throw new IOException("No handshake received from the router");
|
||||
}
|
||||
try {
|
||||
synchronized (_dateReceivedLock) {
|
||||
@@ -327,7 +327,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
|
||||
_producer.disconnect(this);
|
||||
} catch (I2PSessionException ipe) {}
|
||||
closeSocket();
|
||||
throw new IOException("no leaseset");
|
||||
throw new IOException("No tunnels built after waiting 5 minutes... are there network problems?");
|
||||
}
|
||||
synchronized (_leaseSetWait) {
|
||||
try {
|
||||
@@ -346,11 +346,11 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
|
||||
} catch (UnknownHostException uhe) {
|
||||
_closed = true;
|
||||
setOpening(false);
|
||||
throw new I2PSessionException(getPrefix() + "Invalid session configuration", uhe);
|
||||
throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, uhe);
|
||||
} catch (IOException ioe) {
|
||||
_closed = true;
|
||||
setOpening(false);
|
||||
throw new I2PSessionException(getPrefix() + "Problem connecting to " + _hostname + " on port " + _portNum, ioe);
|
||||
throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -39,7 +39,7 @@ public interface I2PSessionListener {
|
||||
|
||||
/**
|
||||
* Notify the client that some error occurred
|
||||
* @param null can be null? or not?
|
||||
* @param error can be null? or not?
|
||||
*/
|
||||
void errorOccurred(I2PSession session, String message, Throwable error);
|
||||
}
|
||||
|
@@ -86,10 +86,10 @@ class I2PSimpleSession extends I2PSessionImpl2 {
|
||||
|
||||
} catch (UnknownHostException uhe) {
|
||||
_closed = true;
|
||||
throw new I2PSessionException(getPrefix() + "Bad host ", uhe);
|
||||
throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, uhe);
|
||||
} catch (IOException ioe) {
|
||||
_closed = true;
|
||||
throw new I2PSessionException(getPrefix() + "Problem connecting to " + _hostname + " on port " + _portNum, ioe);
|
||||
throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -164,7 +164,7 @@ JXQAnA28vDmMMMH/WPbC5ixmJeGGNUiR
|
||||
addKey(propertyTrustedKeysTokens.nextToken().trim(), "");
|
||||
|
||||
} else {
|
||||
addKey(DEFAULT_TRUSTED_KEY, "jrandom@mail.i2p");
|
||||
//addKey(DEFAULT_TRUSTED_KEY, "jrandom@mail.i2p");
|
||||
addKey(DEFAULT_TRUSTED_KEY2, "zzz@mail.i2p");
|
||||
//addKey(DEFAULT_TRUSTED_KEY3, "complication@mail.i2p");
|
||||
addKey(DEFAULT_TRUSTED_KEY4, "HungryHobo@mail.i2p");
|
||||
|
@@ -80,10 +80,13 @@ public class PrivateKeyFile {
|
||||
if (args[0].equals("-n")) {
|
||||
// Cert constructor generates a null cert
|
||||
pkf.setCertType(Certificate.CERTIFICATE_TYPE_NULL);
|
||||
System.out.println("New destination with null cert is:");
|
||||
} else if (args[0].equals("-u")) {
|
||||
pkf.setCertType(99);
|
||||
System.out.println("New destination with unknown cert is:");
|
||||
} else if (args[0].equals("-x")) {
|
||||
pkf.setCertType(Certificate.CERTIFICATE_TYPE_HIDDEN);
|
||||
System.out.println("New destination with hidden cert is:");
|
||||
} else if (args[0].equals("-h")) {
|
||||
int hashEffort = HASH_EFFORT;
|
||||
if (args.length == 3)
|
||||
@@ -91,12 +94,13 @@ public class PrivateKeyFile {
|
||||
System.out.println("Estimating hashcash generation time, stand by...");
|
||||
System.out.println(estimateHashCashTime(hashEffort));
|
||||
pkf.setHashCashCert(hashEffort);
|
||||
System.out.println("New destination with hashcash cert is:");
|
||||
} else if (args.length == 3 && args[0].equals("-s")) {
|
||||
// Sign dest1 with dest2's Signing Private Key
|
||||
PrivateKeyFile pkf2 = new PrivateKeyFile(args[2]);
|
||||
pkf.setSignedCert(pkf2);
|
||||
System.out.println("New destination with signed cert is:");
|
||||
}
|
||||
System.out.println("New signed destination is:");
|
||||
System.out.println(pkf);
|
||||
pkf.write();
|
||||
verifySignature(d);
|
||||
@@ -318,23 +322,56 @@ public class PrivateKeyFile {
|
||||
byte[] data = new byte[len];
|
||||
System.arraycopy(d.getPublicKey().getData(), 0, data, 0, PublicKey.KEYSIZE_BYTES);
|
||||
System.arraycopy(d.getSigningPublicKey().getData(), 0, data, PublicKey.KEYSIZE_BYTES, SigningPublicKey.KEYSIZE_BYTES);
|
||||
Signature sig = new Signature(d.getCertificate().getPayload());
|
||||
Signature sig = new Signature();
|
||||
byte[] payload = d.getCertificate().getPayload();
|
||||
Hash signerHash = null;
|
||||
if (payload == null) {
|
||||
System.out.println("Bad signed cert - no payload");
|
||||
return false;
|
||||
} else if (payload.length == Signature.SIGNATURE_BYTES) {
|
||||
sig.setData(payload);
|
||||
} else if (payload.length == Certificate.CERTIFICATE_LENGTH_SIGNED_WITH_HASH) {
|
||||
byte[] pl = new byte[Signature.SIGNATURE_BYTES];
|
||||
System.arraycopy(payload, 0, pl, 0, Signature.SIGNATURE_BYTES);
|
||||
sig.setData(pl);
|
||||
byte[] hash = new byte[Hash.HASH_LENGTH];
|
||||
System.arraycopy(payload, Signature.SIGNATURE_BYTES, hash, 0, Hash.HASH_LENGTH);
|
||||
signerHash = new Hash(hash);
|
||||
System.out.println("Destination is signed by " + Base32.encode(hash) + ".b32.i2p");
|
||||
} else {
|
||||
System.out.println("Bad signed cert - length = " + payload.length);
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] filenames = new String[] {"privatehosts.txt", "userhosts.txt", "hosts.txt"};
|
||||
int tried = 0;
|
||||
for (int i = 0; i < filenames.length; i++) {
|
||||
Properties hosts = new Properties();
|
||||
try {
|
||||
File f = new File(filenames[i]);
|
||||
if ( (f.exists()) && (f.canRead()) ) {
|
||||
DataHelper.loadProps(hosts, f, true);
|
||||
int sz = hosts.size();
|
||||
if (sz > 0) {
|
||||
tried += sz;
|
||||
if (signerHash == null)
|
||||
System.out.println("Attempting to verify using " + sz + " hosts, this may take a while");
|
||||
}
|
||||
|
||||
for (Iterator iter = hosts.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String s = (String) entry.getValue();
|
||||
Destination signer = new Destination(s);
|
||||
if (checkSignature(sig, data, signer.getSigningPublicKey())) {
|
||||
System.out.println("Good signature from: " + entry.getKey());
|
||||
return true;
|
||||
// make it go faster if we have the signerHash hint
|
||||
if (signerHash == null || signer.calculateHash().equals(signerHash)) {
|
||||
if (checkSignature(sig, data, signer.getSigningPublicKey())) {
|
||||
System.out.println("Good signature from: " + entry.getKey());
|
||||
return true;
|
||||
}
|
||||
if (signerHash != null) {
|
||||
System.out.println("Bad signature from: " + entry.getKey());
|
||||
// could probably return false here but keep going anyway
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,7 +379,10 @@ public class PrivateKeyFile {
|
||||
}
|
||||
// not found, continue to the next file
|
||||
}
|
||||
System.out.println("No valid signer found");
|
||||
if (tried > 0)
|
||||
System.out.println("No valid signer found");
|
||||
else
|
||||
System.out.println("No addressbooks found to valididate signer");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -5,15 +5,14 @@ import java.io.File;
|
||||
/**
|
||||
* Same as File but sets the file mode after mkdir() so it can
|
||||
* be read and written by the owner only (i.e. 700 on linux)
|
||||
* As of 0.8.2, just use SecureFile instead of this.
|
||||
*
|
||||
* @since 0.8.1
|
||||
* @author zzz
|
||||
*/
|
||||
public class SecureDirectory extends File {
|
||||
|
||||
private static final boolean canSetPerms =
|
||||
(new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0;
|
||||
private static final boolean isNotWindows = !System.getProperty("os.name").startsWith("Win");
|
||||
protected static final boolean isNotWindows = !System.getProperty("os.name").startsWith("Win");
|
||||
|
||||
public SecureDirectory(String pathname) {
|
||||
super(pathname);
|
||||
@@ -54,8 +53,8 @@ public class SecureDirectory extends File {
|
||||
* Tries to set the permissions to 700,
|
||||
* ignores errors
|
||||
*/
|
||||
private void setPerms() {
|
||||
if (!canSetPerms)
|
||||
protected void setPerms() {
|
||||
if (!SecureFileOutputStream.canSetPerms())
|
||||
return;
|
||||
try {
|
||||
setReadable(false, false);
|
||||
|
81
core/java/src/net/i2p/util/SecureFile.java
Normal file
81
core/java/src/net/i2p/util/SecureFile.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package net.i2p.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Same as SecureDirectory but sets the file mode after createNewFile()
|
||||
* and createTempFile() also. So just use this instead.
|
||||
* Probably should have just made this class in the beginning and not had two.
|
||||
*
|
||||
* @since 0.8.2
|
||||
* @author zzz
|
||||
*/
|
||||
public class SecureFile extends SecureDirectory {
|
||||
|
||||
public SecureFile(String pathname) {
|
||||
super(pathname);
|
||||
}
|
||||
|
||||
public SecureFile(String parent, String child) {
|
||||
super(parent, child);
|
||||
}
|
||||
|
||||
public SecureFile(File parent, String child) {
|
||||
super(parent, child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets file to mode 600 if the file is created
|
||||
*/
|
||||
@Override
|
||||
public boolean createNewFile() throws IOException {
|
||||
boolean rv = super.createNewFile();
|
||||
if (rv)
|
||||
setPerms();
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets file to mode 600 when the file is created
|
||||
*/
|
||||
public static File createTempFile(String prefix, String suffix) throws IOException {
|
||||
File rv = File.createTempFile(prefix, suffix);
|
||||
// same thing as below but static
|
||||
SecureFileOutputStream.setPerms(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets file to mode 600 when the file is created
|
||||
*/
|
||||
public static File createTempFile(String prefix, String suffix, File directory) throws IOException {
|
||||
File rv = File.createTempFile(prefix, suffix, directory);
|
||||
// same thing as below but static
|
||||
SecureFileOutputStream.setPerms(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to set the permissions to 600,
|
||||
* ignores errors
|
||||
*/
|
||||
@Override
|
||||
protected void setPerms() {
|
||||
if (!SecureFileOutputStream.canSetPerms())
|
||||
return;
|
||||
try {
|
||||
setReadable(false, false);
|
||||
setReadable(true, true);
|
||||
setWritable(false, false);
|
||||
setWritable(true, true);
|
||||
if (isNotWindows && isDirectory()) {
|
||||
setExecutable(false, false);
|
||||
setExecutable(true, true);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// NoSuchMethodException or NoSuchMethodError if we somehow got the
|
||||
// version detection wrong or the JVM doesn't support it
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,6 +4,8 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
/**
|
||||
* Same as FileOutputStream but sets the file mode so it can only
|
||||
* be read and written by the owner only (i.e. 600 on linux)
|
||||
@@ -13,7 +15,7 @@ import java.io.FileOutputStream;
|
||||
*/
|
||||
public class SecureFileOutputStream extends FileOutputStream {
|
||||
|
||||
private static final boolean canSetPerms =
|
||||
private static final boolean oneDotSix =
|
||||
(new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0;
|
||||
|
||||
/**
|
||||
@@ -51,12 +53,22 @@ public class SecureFileOutputStream extends FileOutputStream {
|
||||
setPerms(file);
|
||||
}
|
||||
|
||||
/** @since 0.8.2 */
|
||||
static boolean canSetPerms() {
|
||||
if (!oneDotSix)
|
||||
return false;
|
||||
I2PAppContext ctx = I2PAppContext.getCurrentContext();
|
||||
if (ctx == null)
|
||||
return true;
|
||||
return !ctx.getBooleanProperty("i2p.insecureFiles");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to set the permissions to 600,
|
||||
* ignores errors
|
||||
*/
|
||||
public static void setPerms(File f) {
|
||||
if (!canSetPerms)
|
||||
if (!canSetPerms())
|
||||
return;
|
||||
try {
|
||||
f.setReadable(false, false);
|
||||
|
@@ -34,7 +34,7 @@ clientApp.3.startOnLoad=true
|
||||
# load a browser pointing at the web console whenever we start up
|
||||
clientApp.4.main=net.i2p.apps.systray.UrlLauncher
|
||||
clientApp.4.name=Open Router Console in web browser at startup
|
||||
clientApp.4.args=http://127.0.0.1:7657/index.jsp
|
||||
clientApp.4.args=http://127.0.0.1:7657/
|
||||
clientApp.4.delay=3
|
||||
clientApp.4.startOnLoad=true
|
||||
|
||||
|
7
installer/resources/proxy/README.txt
Normal file
7
installer/resources/proxy/README.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Note to translators and editors:
|
||||
|
||||
These are the error pages displayed in the HTTP proxy,
|
||||
with the HTTP headers prepended.
|
||||
|
||||
All files in this directory must be DOS formatted with \r\n line endings,
|
||||
so the HTTP header lines are standards-compliant. Thank you.
|
@@ -492,7 +492,7 @@ public class TransportManager implements TransportEventListener {
|
||||
t.renderStatusHTML(out, urlBase, sortFlags);
|
||||
}
|
||||
|
||||
if (_transports.size() > 0) {
|
||||
if (!_transports.isEmpty()) {
|
||||
out.write(getTransportsLegend());
|
||||
}
|
||||
|
||||
@@ -516,6 +516,11 @@ public class TransportManager implements TransportEventListener {
|
||||
|
||||
private final String getTransportsLegend() {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<h3 id=\"help\">").append(_("Help")).append("</h3><div class=\"configure\"><p>")
|
||||
.append(_("Your transport connection limits are automatically set based on your configured bandwidth."))
|
||||
.append('\n')
|
||||
.append(_("To override these limits, add the settings i2np.ntcp.maxConnections=nnn and i2np.udp.maxConnections=nnn on the advanced configuration page."))
|
||||
.append("</p></div>\n");
|
||||
buf.append("<h3>").append(_("Definitions")).append("</h3><div class=\"configure\">" +
|
||||
"<p><b id=\"def.peer\">").append(_("Peer")).append("</b>: ").append(_("The remote peer, identified by router hash")).append("<br>\n" +
|
||||
"<b id=\"def.dir\">").append(_("Dir")).append("</b>: " +
|
||||
|
@@ -1978,15 +1978,13 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
// buf.append(' ').append(_context.blocklist().toStr(ip));
|
||||
buf.append("</td>");
|
||||
|
||||
long idleIn = (now-peer.getLastReceiveTime())/1000;
|
||||
long idleOut = (now-peer.getLastSendTime())/1000;
|
||||
if (idleIn < 0) idleIn = 0;
|
||||
if (idleOut < 0) idleOut = 0;
|
||||
long idleIn = Math.max(now-peer.getLastReceiveTime(), 0);
|
||||
long idleOut = Math.max(now-peer.getLastSendTime(), 0);
|
||||
|
||||
buf.append("<td class=\"cells\" align=\"right\">");
|
||||
buf.append(DataHelper.formatDuration2(1000 * idleIn));
|
||||
buf.append(DataHelper.formatDuration2(idleIn));
|
||||
buf.append("&thinsp/ ");
|
||||
buf.append(DataHelper.formatDuration2(1000 * idleOut));
|
||||
buf.append(DataHelper.formatDuration2(idleOut));
|
||||
buf.append("</td>");
|
||||
|
||||
int recvBps = (idleIn > 2 ? 0 : peer.getReceiveBps());
|
||||
@@ -2010,7 +2008,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
buf.append("</td>");
|
||||
|
||||
buf.append("<td class=\"cells\" align=\"right\">");
|
||||
buf.append(DataHelper.formatDuration2(peer.getClockSkew()));
|
||||
long skew = peer.getClockSkew();
|
||||
buf.append(formatDuration3(peer.getClockSkew()));
|
||||
buf.append("</td>");
|
||||
offsetTotal = offsetTotal + peer.getClockSkew();
|
||||
|
||||
@@ -2032,15 +2031,15 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
int rto = peer.getRTO();
|
||||
|
||||
buf.append("<td class=\"cells\" align=\"right\">");
|
||||
buf.append(rtt);
|
||||
buf.append(DataHelper.formatDuration2(rtt));
|
||||
buf.append("</td>");
|
||||
|
||||
buf.append("<td class=\"cells\" align=\"right\">");
|
||||
buf.append(peer.getRTTDeviation());
|
||||
buf.append(DataHelper.formatDuration2(peer.getRTTDeviation()));
|
||||
buf.append("</td>");
|
||||
|
||||
buf.append("<td class=\"cells\" align=\"right\">");
|
||||
buf.append(rto);
|
||||
buf.append(DataHelper.formatDuration2(rto));
|
||||
buf.append("</td>");
|
||||
|
||||
buf.append("<td class=\"cells\" align=\"right\">");
|
||||
@@ -2104,19 +2103,19 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
// buf.append("<tr><td colspan=\"16\"><hr></td></tr>\n");
|
||||
buf.append("<tr class=\"tablefooter\"> <td colspan=\"3\" align=\"left\"><b>").append(_("SUMMARY")).append("</b></td>" +
|
||||
"<td align=\"center\" nowrap><b>");
|
||||
buf.append(formatKBps(bpsIn)).append("thinsp;/ ").append(formatKBps(bpsOut));
|
||||
buf.append(formatKBps(bpsIn)).append(" / ").append(formatKBps(bpsOut));
|
||||
long x = numPeers > 0 ? uptimeMsTotal/numPeers : 0;
|
||||
buf.append("</b></td>" +
|
||||
"<td align=\"center\"><b>").append(DataHelper.formatDuration2(x));
|
||||
x = numPeers > 0 ? offsetTotal/numPeers : 0;
|
||||
buf.append("</b></td><td align=\"center\"><b>").append(DataHelper.formatDuration2(x)).append("</b></td>\n" +
|
||||
buf.append("</b></td><td align=\"center\"><b>").append(formatDuration3(x)).append("</b></td>\n" +
|
||||
"<td align=\"center\"><b>");
|
||||
buf.append(numPeers > 0 ? cwinTotal/(numPeers*1024) + "K" : "0K");
|
||||
buf.append("</b></td><td> </td>\n" +
|
||||
"<td align=\"center\"><b>");
|
||||
buf.append(numPeers > 0 ? rttTotal/numPeers : 0);
|
||||
buf.append(numPeers > 0 ? DataHelper.formatDuration2(rttTotal/numPeers) : '0');
|
||||
buf.append("</b></td><td> </td> <td align=\"center\"><b>");
|
||||
buf.append(numPeers > 0 ? rtoTotal/numPeers : 0);
|
||||
buf.append(numPeers > 0 ? DataHelper.formatDuration2(rtoTotal/numPeers) : '0');
|
||||
buf.append("</b></td><td> </td> <td align=\"center\"><b>");
|
||||
buf.append(sendTotal).append("</b></td> <td align=\"center\"><b>").append(recvTotal).append("</b></td>\n" +
|
||||
"<td align=\"center\"><b>").append(resentTotal);
|
||||
@@ -2139,6 +2138,17 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
buf.setLength(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return e.g. 3 sec or -3 sec
|
||||
* formatDuration2() always prints negative numbers in ms
|
||||
* @since 0.8.2
|
||||
*/
|
||||
private static String formatDuration3(long x) {
|
||||
if (x >= 0)
|
||||
return DataHelper.formatDuration2(x);
|
||||
return "-" + DataHelper.formatDuration2(0 - x);
|
||||
}
|
||||
|
||||
private static final DecimalFormat _fmt = new DecimalFormat("#,##0.00");
|
||||
private static final String formatKBps(int bps) {
|
||||
synchronized (_fmt) {
|
||||
|
Reference in New Issue
Block a user