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..7ca924326 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java @@ -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/core/java/src/net/i2p/I2PException.java b/core/java/src/net/i2p/I2PException.java index d263766ef..70b7fdbfc 100644 --- a/core/java/src/net/i2p/I2PException.java +++ b/core/java/src/net/i2p/I2PException.java @@ -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); } -} \ No newline at end of file + + /** @since 0.8.2 */ + public I2PException(Throwable cause) { + super(cause); + } +} diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java index cd60b60cc..783222bc9 100644 --- a/core/java/src/net/i2p/client/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionImpl.java @@ -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); } } diff --git a/core/java/src/net/i2p/client/I2PSimpleSession.java b/core/java/src/net/i2p/client/I2PSimpleSession.java index af5ab9a75..f4bc3e812 100644 --- a/core/java/src/net/i2p/client/I2PSimpleSession.java +++ b/core/java/src/net/i2p/client/I2PSimpleSession.java @@ -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); } }