diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java index 6fc491e394acb65c4bbb7af19f07fe007e28b03e..34dc025d56f802e0904c0b0605efb485ba019404 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java @@ -887,13 +887,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (portNum <= 0) throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]); - I2PTunnelTask task; ownDest = !isShared; try { String privateKeyFile = null; if (args.length >= 4) privateKeyFile = args[3]; - task = new I2PTunnelClient(portNum, args[1], l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PTunnelClient(portNum, args[1], l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("clientTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -966,10 +966,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } } - I2PTunnelTask task; ownDest = !isShared; try { - task = new I2PTunnelHTTPClient(clientPort, l, ownDest, proxy, this, this); + I2PTunnelClientBase task = new I2PTunnelHTTPClient(clientPort, l, ownDest, proxy, this, this); + task.startRunning(); addtask(task); notifyEvent("httpclientTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1035,10 +1035,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } } - I2PTunnelTask task; ownDest = !isShared; try { - task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, this, this); + I2PTunnelClientBase task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, this, this); + task.startRunning(); addtask(task); } catch (IllegalArgumentException iae) { String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at " + host + ':'+ port + @@ -1097,13 +1097,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } } - I2PTunnelTask task; ownDest = !isShared; try { String privateKeyFile = null; if (args.length >= 4) privateKeyFile = args[3]; - task = new I2PTunnelIRCClient(_port, args[1], l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PTunnelIRCClient(_port, args[1], l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("ircclientTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1160,7 +1160,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (args.length == 3) privateKeyFile = args[2]; try { - I2PTunnelTask task = new I2PSOCKSTunnel(_port, l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PSOCKSTunnel(_port, l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1207,7 +1208,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (args.length == 3) privateKeyFile = args[2]; try { - I2PTunnelTask task = new I2PSOCKSIRCTunnel(_port, l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PSOCKSIRCTunnel(_port, l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1670,7 +1672,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (!_clientOptions.containsKey("outbound.nickname")) _clientOptions.setProperty("outbound.nickname", "I2Ping"); } - I2PTunnelTask task = new I2Ping(l, ownDest, this, this); + I2PTunnelClientBase task = new I2Ping(l, ownDest, this, this); + task.startRunning(); addtask(task); notifyEvent("pingTaskId", Integer.valueOf(task.getId())); } else { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java index 6a552719ec1d0cf3bf7339a9bc4d4a47d396c1fd..93785e32659d957842660dfb0d96ef8c4c3d1989 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java @@ -32,6 +32,9 @@ public class I2PTunnelClient extends I2PTunnelClientBase { protected long readTimeout = DEFAULT_READ_TIMEOUT; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param destinations peers we target, comma- or space-separated. Since 0.9.9, each dest may be appended with :port * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router @@ -44,11 +47,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase { tunnel, pkf); _addrs = new ArrayList<I2PSocketAddress>(1); - if (waitEventValue("openBaseClientResult").equals("error")) { - notifyEvent("openClientResult", "error"); - return; - } - dests = new ArrayList<Destination>(1); buildAddresses(destinations); @@ -68,9 +66,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase { } setName(getLocalPort() + " -> " + destinations); - - startRunning(); - notifyEvent("openClientResult", "ok"); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java index 030e4a0b637da4aa3d4554a4831b50fd638225c2..a2c408973d82ec4be7fc817e4572d7bb20adb892 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java @@ -26,6 +26,7 @@ import javax.net.ssl.SSLServerSocketFactory; import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.I2PSession; +import net.i2p.client.I2PSessionException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManagerFactory; @@ -53,6 +54,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna protected Destination dest; private int localPort; + private final String _handlerName; /** * Protected for I2Ping since 0.9.11. Not for use outside package. @@ -91,6 +93,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna chained = true; sockMgr = sktMgr; _clientId = clientId; + _handlerName = "chained"; this.localPort = localPort; this.l = l; _ownDest = true; // == ! shared client @@ -101,31 +104,14 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna _context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); _log = _context.logManager().getLog(getClass()); - Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort); - t.start(); - open = true; - synchronized (this) { - while (!listenerReady && open) { - try { - wait(); - } catch (InterruptedException e) { - // ignore - } - } - } - - if (open && listenerReady) { - l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort); - notifyEvent("openBaseClientResult", "ok"); - } else { - l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs"); - notifyEvent("openBaseClientResult", "error"); - } + startup(); } /** * The main constructor. - * This may take a LONG time if building and starting a new manager. + * + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. * * @param localPort if 0, use any port, get actual port selected with getLocalPort() * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -139,7 +125,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * Use this to build a client with a persistent private key. - * This may take a LONG time if building and starting a new manager. + * + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. * * @param localPort if 0, use any port, get actual port selected with getLocalPort() * @param pkf Path to the private key file, or null to generate a transient key @@ -155,7 +143,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna this.localPort = localPort; this.l = l; _ownDest = ownDest; // == ! shared client - + _handlerName = handlerName; _context = tunnel.getContext(); _context.statManager().createRateStat("i2ptunnel.client.closeBacklog", "How many pending sockets remain when we close one due to backlog?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); @@ -201,33 +189,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } // else delay creating session until createI2PSocket() is called - Thread t = new I2PAppThread(this); - t.setName("Client " + _clientId); - t.start(); - open = true; - synchronized (this) { - while (!listenerReady && open) { - try { - wait(); - } catch (InterruptedException e) { - // ignore - } - } - } - - if (open && listenerReady) { - if (openNow) - l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort); - else - l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort + ", delaying tunnel open until required"); - notifyEvent("openBaseClientResult", "ok"); - } else { - l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs"); - notifyEvent("openBaseClientResult", "error"); - } } /** + * Create the manager if it doesn't exist, AND connect it to the router and + * build tunnels. + * * Sets the this.sockMgr field if it is null, or if we want a new one. * This may take a LONG time if building a new manager. * @@ -269,6 +236,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna this.sockMgr = getSocketManager(); } } + connectManager(); } /** this is ONLY for shared clients */ @@ -277,7 +245,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * This is ONLY for shared clients. - * This may take a LONG time if building a new manager. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -289,7 +258,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * This is ONLY for shared clients. - * This may take a LONG time if building a new manager. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -301,7 +271,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * This is ONLY for shared clients. - * This may take a LONG time if building a new manager. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -347,7 +318,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } /** - * This may take a LONG time. + * For NON-SHARED clients (ownDest = true). + * + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -356,8 +330,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna protected I2PSocketManager buildSocketManager() { return buildSocketManager(getTunnel(), this.privKeyFile, this.l); } + /** - * This may take a LONG time. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -371,7 +347,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna private static final int MAX_RETRIES = 4; /** - * This may take a LONG time. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @param pkf absolute path or null * @return non-null @@ -383,7 +360,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } /** - * This may take a LONG time. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @param pkf absolute path or null * @return non-null @@ -400,57 +378,79 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna try { portNum = Integer.parseInt(tunnel.port); } catch (NumberFormatException nfe) { - _log.log(Log.CRIT, "Invalid port specified [" + tunnel.port + "], reverting to " + portNum); + throw new IllegalArgumentException("Invalid port specified [" + tunnel.port + "]", nfe); } } I2PSocketManager sockManager = null; - // FIXME: Can't stop a tunnel from the UI while it's in this loop (no session yet) - int retries = 0; - while (sockManager == null) { + FileInputStream fis = null; + try { if (pkf != null) { // Persistent client dest - FileInputStream fis = null; - try { - 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); - throw new IllegalArgumentException("Error opening key file " + ioe); - } finally { - if (fis != null) - try { fis.close(); } catch (IOException ioe) {} - } + fis = new FileInputStream(pkf); + sockManager = I2PSocketManagerFactory.createDisconnectedManager(fis, tunnel.host, portNum, props); } else { - sockManager = I2PSocketManagerFactory.createManager(tunnel.host, portNum, props); + sockManager = I2PSocketManagerFactory.createDisconnectedManager(null, tunnel.host, portNum, props); } - - if (sockManager == null) { - // 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 + + } catch (I2PSessionException ise) { + throw new IllegalArgumentException("Can't create socket manager", ise); + } catch (IOException ioe) { + if (log != null) + log.log("Error opening key file " + ioe); + _log.error("Error opening key file", ioe); + throw new IllegalArgumentException("Error opening key file", ioe); + } finally { + if (fis != null) + try { fis.close(); } catch (IOException ioe) {} + } + sockManager.setName("Client"); + if (_log.shouldLog(Log.INFO)) + _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Built a new socket manager [s=" + sockManager.getSession() + "]"); + tunnel.addSession(sockManager.getSession()); + return sockManager; + } + + + /** + * Warning, blocks while connecting to router and building tunnels; + * This may take a LONG time. + * + * @throws IllegalArgumentException if the I2CP configuration is b0rked so + * badly that we cant create a socketManager + * @since 0.9.20 + */ + private void connectManager() { + int retries = 0; + while (sockMgr.getSession().isClosed()) { + try { + sockMgr.getSession().connect(); + } catch (I2PSessionException ise) { + // shadows instance _log + Log _log = getTunnel().getContext().logManager().getLog(I2PTunnelClientBase.class); + Logging log = this.l; + // try to make this error sensible as it will happen... + String portNum = getTunnel().port; + if (portNum == null) + portNum = "7654"; + String msg; + if (getTunnel().getContext().isRouterContext()) + msg = "Unable to connect to the router at " + getTunnel().host + ':' + portNum + " and build tunnels for the client"; + else + msg = "Unable to 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"); + _log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds", ise); } 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); + _log.log(Log.CRIT, msg + ", giving up", ise); + throw new IllegalArgumentException(msg, ise); } try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {} } } - sockManager.setName("Client"); - if (_log.shouldLog(Log.INFO)) - _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Built a new socket manager [s=" + sockManager.getSession() + "]"); - tunnel.addSession(sockManager.getSession()); - return sockManager; } public final int getLocalPort() { @@ -469,11 +469,67 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } /** - * Actually start working on incoming connections. *Must* be + * Actually open the local socket and start working on incoming connections. *Must* be * called by derived classes after initialization. * + * (this wasn't actually true until 0.9.20) + * + * This will be fast if i2cp.delayOpen is true, but could take + * a LONG TIME if it is false, as it connects to the router and builds tunnels. + * */ public void startRunning() { + boolean openNow = !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.delayOpen")); + if (openNow) { + while (sockMgr == null) { + verifySocketManager(); + if (sockMgr == null) { + _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) {} + } + } + // can't be null unless we limit the loop above + //if (sockMgr == null) { + // l.log("Invalid I2CP configuration"); + // throw new IllegalArgumentException("Socket manager could not be created"); + //} + l.log("Tunnels ready for client: " + _handlerName); + + } // else delay creating session until createI2PSocket() is called + startup(); + } + + private void startup() { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("startup " + _clientId, new Exception("I did it")); + // prevent JVM exit when running outside the router + boolean isDaemon = getTunnel().getContext().isRouterContext(); + Thread t = new I2PAppThread(this, "Client " + _clientId, isDaemon); + t.start(); + open = true; + synchronized (this) { + while (!listenerReady && open) { + try { + wait(); + } catch (InterruptedException e) { + // ignore + } + } + } + + if (open && listenerReady) { + boolean openNow = !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.delayOpen")); + if (openNow) + l.log("Client ready, listening on " + getTunnel().listenHost + ':' + localPort); + else + l.log("Client ready, listening on " + getTunnel().listenHost + ':' + localPort + ", delaying tunnel open until required"); + notifyEvent("openBaseClientResult", "ok"); + } else { + l.log("Client error for " + getTunnel().listenHost + ':' + localPort + ", check logs"); + notifyEvent("openBaseClientResult", "error"); + } synchronized (startLock) { startRunning = true; startLock.notify(); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java index e10cfb55f6d717f1321157aefe9ebb1636e258c5..8763218662b4327eff0c4d14abdb5ab789b568e7 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java @@ -77,6 +77,9 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R "Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.<BR>"; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router */ @@ -85,11 +88,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R I2PTunnel tunnel) throws IllegalArgumentException { super(localPort, ownDest, l, notifyThis, "HTTPS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel); - if (waitEventValue("openBaseClientResult").equals("error")) { - notifyEvent("openConnectClientResult", "error"); - return; - } - if (wwwProxy != null) { StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); while (tok.hasMoreTokens()) @@ -97,8 +95,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R } setName("HTTPS Proxy on " + tunnel.listenHost + ':' + localPort); - - startRunning(); } /** diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java index 56c2e7550c4242fb5146880a2968f198972f2f6c..4dbd5e654cdce76ed02115679be940f818244cd2 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java @@ -30,6 +30,9 @@ public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runn /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router */ @@ -38,8 +41,6 @@ public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runn // proxyList = new ArrayList(); setName(getLocalPort() + " -> HTTPClient [NO PROXIES]"); - startRunning(); - notifyEvent("openHTTPClientResult", "ok"); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java index d97482e04e118cdf618b70067f415fb5d8e43bfe..2a3118567c963a66b0a32d90dbf4f837620bdc70 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java @@ -32,7 +32,9 @@ public class I2PTunnelHTTPBidirServer extends I2PTunnelHTTPServer { bidir = true; /* start the httpclient */ - task = new I2PTunnelHTTPBidirProxy(localPort, l, sockMgr, getTunnel(), getEventDispatcher(), __serverId); + I2PTunnelClientBase client = new I2PTunnelHTTPBidirProxy(localPort, l, sockMgr, getTunnel(), getEventDispatcher(), __serverId); + client.startRunning(); + task = client; sockMgr.setName("Server"); // TO-DO: Need to change this to "Bidir"! getTunnel().addSession(sockMgr.getSession()); l.log("Ready!"); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index e8912cd112be40efb75e2e5260a29e325e98724a..372648b4ee45f6003e233e71465fe2a80817ed9a 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -192,6 +192,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn * This constructor always starts the tunnel (ignoring the i2cp.delayOpen option). * It is used to add a client to an existing socket manager. * + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param sockMgr the existing socket manager */ public I2PTunnelHTTPClient(int localPort, Logging l, I2PSocketManager sockMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) { @@ -200,12 +203,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // proxyList = new ArrayList(); setName("HTTP Proxy on " + getTunnel().listenHost + ':' + localPort); - startRunning(); - notifyEvent("openHTTPClientResult", "ok"); } /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router */ @@ -216,10 +220,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn _proxyNonce = Long.toString(_context.random().nextLong()); //proxyList = new ArrayList(); // We won't use outside of i2p - if(waitEventValue("openBaseClientResult").equals("error")) { - notifyEvent("openHTTPClientResult", "error"); - return; - } if(wwwProxy != null) { StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); @@ -229,9 +229,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } setName("HTTP Proxy on " + tunnel.listenHost + ':' + localPort); - - startRunning(); - notifyEvent("openHTTPClientResult", "ok"); } @@ -611,6 +608,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn _("i2paddresshelper cannot help you with a destination like that!") + "</p>").getBytes("UTF-8")); writeFooter(out); + reader.drain(); // XXX: should closeSocket(s) be in a finally block? } catch (IOException ioe) { // ignore @@ -725,7 +723,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn out.write(getErrorPage("localhost", ERR_LOCALHOST).getBytes("UTF-8")); writeFooter(out); reader.drain(); - s.close(); } catch (IOException ioe) { // ignore } finally { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java index 344c721971d42de85651596be45a84567ca8497b..e8fac6812b3aded6253952d2fadc22d6eee48221 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java @@ -41,6 +41,9 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { public static final String PROP_DCC = "i2ptunnel.ircclient.enableDCC"; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param destinations peers we target, comma- or space-separated. Since 0.9.9, each dest may be appended with :port * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router @@ -81,8 +84,6 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { _dccEnabled = Boolean.parseBoolean(tunnel.getClientOptions().getProperty(PROP_DCC)); // TODO add some prudent tunnel options (or is it too late?) - startRunning(); - notifyEvent("openIRCClientResult", "ok"); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java index 5d6dbcef3ec88f5c7699acd780df88ae4cb237dc..5c06cb41c2d5ead872c13ee45d977286b65a1f20 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java @@ -276,7 +276,7 @@ public class TunnelControllerGroup implements ClientApp { for (int i = 0; i < _controllers.size(); i++) { TunnelController controller = _controllers.get(i); if (controller.getStartOnLoad()) - controller.startTunnel(); + controller.startTunnelBackground(); } } finally { _controllersLock.readLock().unlock(); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java index 42af9abf220afd602473c5af32392db3d7ba6c54..753da65ec466f3c740804aa8c02204ce813085ce 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java @@ -109,6 +109,7 @@ public class DCCClientManager extends EventReceiver { I2PTunnelDCCClient cTunnel = new I2PTunnelDCCClient(b32, localPort, port, l, sockMgr, _dispatch, _tunnel, ++_id); cTunnel.attachEventDispatcher(this); + cTunnel.startRunning(); int lport = cTunnel.getLocalPort(); if (_log.shouldLog(Log.WARN)) _log.warn("Opened client tunnel at port " + lport + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java index fcca71cb9a5cb90aafc215dc43abe631366ec13d..f5b434e3be058c4d1ecff900da526e27bb4addfb 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java @@ -37,6 +37,9 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase { public static final String CONNECT_STOP_EVENT = "connectionStopped"; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param dest the target, presumably b32 * @param localPort if 0, use any port, get actual port selected with getLocalPort() * @throws IllegalArgumentException if the I2PTunnel does not contain @@ -51,8 +54,6 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase { _expires = tunnel.getContext().clock().now() + INBOUND_EXPIRE; setName("DCC send -> " + dest + ':' + remotePort); - - startRunning(); } /** 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 498d75a181cd8e0366eb51ba7d9a19cba8ed0c7f..6f8f6b3d302dccea16873dbf1ec86f6e712514ff 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java @@ -33,7 +33,12 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase { // I2PSOCKSTunnel(localPort, l, ownDest, (EventDispatcher)null); //} - /** @param pkf private key file name or null for transient key */ + /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * + * @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, "SOCKS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel, pkf); @@ -44,8 +49,6 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase { setName("SOCKS Proxy on " + tunnel.listenHost + ':' + localPort); parseOptions(); - startRunning(); - notifyEvent("openSOCKSTunnelResult", "ok"); }