diff --git a/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java b/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java index 30536f4ae..22bf33b5c 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java @@ -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); diff --git a/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java b/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java index c963ecce5..ac471df80 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java @@ -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); diff --git a/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java b/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java index 258801011..274fa8c4f 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java @@ -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) {} diff --git a/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java b/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java index 7c9e65994..b2ff2c511 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java @@ -27,7 +27,7 @@ package net.i2p.addressbook; * @author Ragnarok * */ -public class DaemonThread extends Thread { +class DaemonThread extends Thread { private String[] args; diff --git a/apps/addressbook/java/src/net/i2p/addressbook/Log.java b/apps/addressbook/java/src/net/i2p/addressbook/Log.java index a1ba1a2fc..d0f01904f 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/Log.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/Log.java @@ -33,7 +33,7 @@ import java.util.Date; * @author Ragnarok * */ -public class Log { +class Log { private File file; diff --git a/apps/addressbook/java/src/net/i2p/addressbook/Subscription.java b/apps/addressbook/java/src/net/i2p/addressbook/Subscription.java index a97635b12..e391d11e2 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/Subscription.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/Subscription.java @@ -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; } -} \ No newline at end of file + + /** @since 0.8.2 */ + public long getLastFetched() { + return this.lastFetched; + } + + /** @since 0.8.2 */ + public void setLastFetched(long t) { + this.lastFetched = t; + } +} diff --git a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java index b033181e0..6a362b847 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java @@ -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(); } -} \ No newline at end of file +} diff --git a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionList.java b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionList.java index ac5d3236d..d67cd9af5 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionList.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionList.java @@ -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) { } } -} \ No newline at end of file +} diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index 8edc92fdf..001928d47 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -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) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 3e2a4ad63..87aa0d357 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -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); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index e1fb7837f..4ebdbac26 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -174,6 +174,8 @@ public class I2PSnarkServlet extends Default { "\n" + ""); out.write(_("I2PSnark - Anonymous BitTorrent Client")); + if ("2".equals(peerParam)) + out.write(" | Debug Mode"); out.write("\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") || diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java index 17049626c..ec38052cc 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java @@ -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 "); 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 [ []]"); 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 "); 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; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java index 71a1561ea..54d31d29e 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java @@ -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(); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java index 16f8447ec..574f723fe 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java @@ -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(); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 14289cf2f..1301fcd2c 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -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(); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java index d0dc227ec..6938a11ef 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java @@ -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(); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java index 96265ff16..fc39e1996 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java @@ -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; } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/InternalSocketRunner.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/InternalSocketRunner.java index d6f4dcc39..edb1434fe 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/InternalSocketRunner.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/InternalSocketRunner.java @@ -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; } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java index 7a9b1dbd6..4299b6d47 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java @@ -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(); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java index f1bc4874c..01888d8d1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java @@ -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); } /** diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java index 740aa4549..14cafbdfd 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java @@ -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(); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java index c21b45ee9..0640c2a31 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java @@ -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 _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() { diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp index be48bb2b9..2b69440ac 100644 --- a/apps/i2ptunnel/jsp/editClient.jsp +++ b/apps/i2ptunnel/jsp/editClient.jsp @@ -29,7 +29,7 @@ -
+
diff --git a/apps/i2ptunnel/jsp/editServer.jsp b/apps/i2ptunnel/jsp/editServer.jsp index 97a0a93c9..773d323a2 100644 --- a/apps/i2ptunnel/jsp/editServer.jsp +++ b/apps/i2ptunnel/jsp/editServer.jsp @@ -29,7 +29,7 @@ - +
diff --git a/apps/i2ptunnel/jsp/index.html b/apps/i2ptunnel/jsp/index.html deleted file mode 100644 index ea1321105..000000000 --- a/apps/i2ptunnel/jsp/index.html +++ /dev/null @@ -1,2 +0,0 @@ -I2P Router Console -Enter diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp index 8b7f8051e..cf0d0067c 100644 --- a/apps/i2ptunnel/jsp/index.jsp +++ b/apps/i2ptunnel/jsp/index.jsp @@ -44,7 +44,7 @@
@@ -53,7 +53,7 @@
@@ -89,7 +89,7 @@ %>
@@ -125,17 +125,17 @@ switch (indexBean.getTunnelStatus(curServer)) { case IndexBean.STARTING: %>
<%=intl._("Starting...")%>
- <%=intl._("Stop")%> + <%=intl._("Stop")%> <% break; case IndexBean.RUNNING: %>
<%=intl._("Running")%>
- <%=intl._("Stop")%> + <%=intl._("Stop")%> <% break; case IndexBean.NOT_RUNNING: %>
<%=intl._("Stopped")%>
- <%=intl._("Start")%> + <%=intl._("Start")%> <% break; } @@ -157,7 +157,7 @@