I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 50b68d4e authored by zzz's avatar zzz
Browse files

propagate from branch 'i2p.i2p.zzz.815' (head 43bce385eecdf95bba08985211b80099d1224462)

            to branch 'i2p.i2p' (head 1b89427bd2952dc4be08fba14ad1d814d722739f)
parents 3f46228f 2f5f91a0
No related branches found
No related tags found
No related merge requests found
Showing
with 190 additions and 134 deletions
...@@ -887,13 +887,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { ...@@ -887,13 +887,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
if (portNum <= 0) if (portNum <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]); throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
I2PTunnelTask task;
ownDest = !isShared; ownDest = !isShared;
try { try {
String privateKeyFile = null; String privateKeyFile = null;
if (args.length >= 4) if (args.length >= 4)
privateKeyFile = args[3]; 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); addtask(task);
notifyEvent("clientTaskId", Integer.valueOf(task.getId())); notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
...@@ -966,10 +966,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { ...@@ -966,10 +966,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
} }
} }
I2PTunnelTask task;
ownDest = !isShared; ownDest = !isShared;
try { try {
task = new I2PTunnelHTTPClient(clientPort, l, ownDest, proxy, this, this); I2PTunnelClientBase task = new I2PTunnelHTTPClient(clientPort, l, ownDest, proxy, this, this);
task.startRunning();
addtask(task); addtask(task);
notifyEvent("httpclientTaskId", Integer.valueOf(task.getId())); notifyEvent("httpclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
...@@ -1035,10 +1035,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { ...@@ -1035,10 +1035,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
} }
} }
I2PTunnelTask task;
ownDest = !isShared; ownDest = !isShared;
try { try {
task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, this, this); I2PTunnelClientBase task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, this, this);
task.startRunning();
addtask(task); addtask(task);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at " + host + ':'+ port + 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 { ...@@ -1097,13 +1097,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
} }
} }
I2PTunnelTask task;
ownDest = !isShared; ownDest = !isShared;
try { try {
String privateKeyFile = null; String privateKeyFile = null;
if (args.length >= 4) if (args.length >= 4)
privateKeyFile = args[3]; 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); addtask(task);
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId())); notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
...@@ -1160,7 +1160,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { ...@@ -1160,7 +1160,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
if (args.length == 3) if (args.length == 3)
privateKeyFile = args[2]; privateKeyFile = args[2];
try { 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); addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId())); notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
...@@ -1207,7 +1208,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { ...@@ -1207,7 +1208,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
if (args.length == 3) if (args.length == 3)
privateKeyFile = args[2]; privateKeyFile = args[2];
try { 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); addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId())); notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
...@@ -1670,7 +1672,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { ...@@ -1670,7 +1672,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
if (!_clientOptions.containsKey("outbound.nickname")) if (!_clientOptions.containsKey("outbound.nickname"))
_clientOptions.setProperty("outbound.nickname", "I2Ping"); _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); addtask(task);
notifyEvent("pingTaskId", Integer.valueOf(task.getId())); notifyEvent("pingTaskId", Integer.valueOf(task.getId()));
} else { } else {
......
...@@ -32,6 +32,9 @@ public class I2PTunnelClient extends I2PTunnelClientBase { ...@@ -32,6 +32,9 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
protected long readTimeout = DEFAULT_READ_TIMEOUT; 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 * @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 * @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router * valid config to contact the router
...@@ -44,11 +47,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase { ...@@ -44,11 +47,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
tunnel, pkf); tunnel, pkf);
_addrs = new ArrayList<I2PSocketAddress>(1); _addrs = new ArrayList<I2PSocketAddress>(1);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openClientResult", "error");
return;
}
dests = new ArrayList<Destination>(1); dests = new ArrayList<Destination>(1);
buildAddresses(destinations); buildAddresses(destinations);
...@@ -68,9 +66,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase { ...@@ -68,9 +66,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
} }
setName(getLocalPort() + " -> " + destinations); setName(getLocalPort() + " -> " + destinations);
startRunning();
notifyEvent("openClientResult", "ok"); notifyEvent("openClientResult", "ok");
} }
......
...@@ -26,6 +26,7 @@ import javax.net.ssl.SSLServerSocketFactory; ...@@ -26,6 +26,7 @@ import javax.net.ssl.SSLServerSocketFactory;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.I2PException; import net.i2p.I2PException;
import net.i2p.client.I2PSession; import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory; import net.i2p.client.streaming.I2PSocketManagerFactory;
...@@ -53,6 +54,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -53,6 +54,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
protected Destination dest; protected Destination dest;
private int localPort; private int localPort;
private final String _handlerName;
/** /**
* Protected for I2Ping since 0.9.11. Not for use outside package. * Protected for I2Ping since 0.9.11. Not for use outside package.
...@@ -91,6 +93,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -91,6 +93,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
chained = true; chained = true;
sockMgr = sktMgr; sockMgr = sktMgr;
_clientId = clientId; _clientId = clientId;
_handlerName = "chained";
this.localPort = localPort; this.localPort = localPort;
this.l = l; this.l = l;
_ownDest = true; // == ! shared client _ownDest = true; // == ! shared client
...@@ -101,31 +104,14 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -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 }); _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()); _log = _context.logManager().getLog(getClass());
Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort); startup();
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");
}
} }
/** /**
* The main constructor. * 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() * @param localPort if 0, use any port, get actual port selected with getLocalPort()
* @throws IllegalArgumentException if the I2CP configuration is b0rked so * @throws IllegalArgumentException if the I2CP configuration is b0rked so
...@@ -139,7 +125,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -139,7 +125,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
/** /**
* Use this to build a client with a persistent private key. * 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 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 * @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 ...@@ -155,7 +143,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
this.localPort = localPort; this.localPort = localPort;
this.l = l; this.l = l;
_ownDest = ownDest; // == ! shared client _ownDest = ownDest; // == ! shared client
_handlerName = handlerName;
_context = tunnel.getContext(); _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 }); _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 ...@@ -201,33 +189,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
} // else delay creating session until createI2PSocket() is called } // 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. * 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. * This may take a LONG time if building a new manager.
* *
...@@ -269,6 +236,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -269,6 +236,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
this.sockMgr = getSocketManager(); this.sockMgr = getSocketManager();
} }
} }
connectManager();
} }
/** this is ONLY for shared clients */ /** this is ONLY for shared clients */
...@@ -277,7 +245,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -277,7 +245,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
/** /**
* This is ONLY for shared clients. * 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 * @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so * @throws IllegalArgumentException if the I2CP configuration is b0rked so
...@@ -289,7 +258,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -289,7 +258,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
/** /**
* This is ONLY for shared clients. * 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 * @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so * @throws IllegalArgumentException if the I2CP configuration is b0rked so
...@@ -301,7 +271,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -301,7 +271,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
/** /**
* This is ONLY for shared clients. * 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 * @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so * @throws IllegalArgumentException if the I2CP configuration is b0rked so
...@@ -347,7 +318,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -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 * @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so * @throws IllegalArgumentException if the I2CP configuration is b0rked so
...@@ -356,8 +330,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -356,8 +330,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
protected I2PSocketManager buildSocketManager() { protected I2PSocketManager buildSocketManager() {
return buildSocketManager(getTunnel(), this.privKeyFile, this.l); 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 * @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so * @throws IllegalArgumentException if the I2CP configuration is b0rked so
...@@ -371,7 +347,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -371,7 +347,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private static final int MAX_RETRIES = 4; 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 * @param pkf absolute path or null
* @return non-null * @return non-null
...@@ -383,7 +360,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -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 * @param pkf absolute path or null
* @return non-null * @return non-null
...@@ -400,57 +378,79 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -400,57 +378,79 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
try { try {
portNum = Integer.parseInt(tunnel.port); portNum = Integer.parseInt(tunnel.port);
} catch (NumberFormatException nfe) { } 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; I2PSocketManager sockManager = null;
// FIXME: Can't stop a tunnel from the UI while it's in this loop (no session yet) FileInputStream fis = null;
int retries = 0; try {
while (sockManager == null) {
if (pkf != null) { if (pkf != null) {
// Persistent client dest // Persistent client dest
FileInputStream fis = null; fis = new FileInputStream(pkf);
try { sockManager = I2PSocketManagerFactory.createDisconnectedManager(fis, tunnel.host, portNum, props);
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) {}
}
} else { } else {
sockManager = I2PSocketManagerFactory.createManager(tunnel.host, portNum, props); sockManager = I2PSocketManagerFactory.createDisconnectedManager(null, tunnel.host, portNum, props);
} }
} catch (I2PSessionException ise) {
if (sockManager == null) { throw new IllegalArgumentException("Can't create socket manager", ise);
// try to make this error sensible as it will happen... sadly we can't get to the listenPort, only the listenHost } catch (IOException ioe) {
String msg = "Unable to connect to the router at " + tunnel.host + ':' + portNum + 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"; " and build tunnels for the client";
else
msg = "Unable to build tunnels for the client";
if (++retries < MAX_RETRIES) { if (++retries < MAX_RETRIES) {
if (log != null) if (log != null)
log.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds"); 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 { } else {
if (log != null) if (log != null)
log.log(msg + ", giving up"); log.log(msg + ", giving up");
_log.log(Log.CRIT, msg + ", giving up"); _log.log(Log.CRIT, msg + ", giving up", ise);
// not clear if callers can handle null throw new IllegalArgumentException(msg, ise);
//return null;
throw new IllegalArgumentException(msg);
} }
try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {} 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() { public final int getLocalPort() {
...@@ -469,11 +469,67 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna ...@@ -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. * 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() { 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) { synchronized (startLock) {
startRunning = true; startRunning = true;
startLock.notify(); startLock.notify();
......
...@@ -77,6 +77,9 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R ...@@ -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>"; "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 * @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router * valid config to contact the router
*/ */
...@@ -85,11 +88,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R ...@@ -85,11 +88,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
I2PTunnel tunnel) throws IllegalArgumentException { I2PTunnel tunnel) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, "HTTPS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel); super(localPort, ownDest, l, notifyThis, "HTTPS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openConnectClientResult", "error");
return;
}
if (wwwProxy != null) { if (wwwProxy != null) {
StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); StringTokenizer tok = new StringTokenizer(wwwProxy, ", ");
while (tok.hasMoreTokens()) while (tok.hasMoreTokens())
...@@ -97,8 +95,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R ...@@ -97,8 +95,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
} }
setName("HTTPS Proxy on " + tunnel.listenHost + ':' + localPort); setName("HTTPS Proxy on " + tunnel.listenHost + ':' + localPort);
startRunning();
} }
/** /**
......
...@@ -30,6 +30,9 @@ public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runn ...@@ -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 * @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router * valid config to contact the router
*/ */
...@@ -38,8 +41,6 @@ public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runn ...@@ -38,8 +41,6 @@ public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runn
// proxyList = new ArrayList(); // proxyList = new ArrayList();
setName(getLocalPort() + " -> HTTPClient [NO PROXIES]"); setName(getLocalPort() + " -> HTTPClient [NO PROXIES]");
startRunning();
notifyEvent("openHTTPClientResult", "ok"); notifyEvent("openHTTPClientResult", "ok");
} }
} }
...@@ -32,7 +32,9 @@ public class I2PTunnelHTTPBidirServer extends I2PTunnelHTTPServer { ...@@ -32,7 +32,9 @@ public class I2PTunnelHTTPBidirServer extends I2PTunnelHTTPServer {
bidir = true; bidir = true;
/* start the httpclient */ /* 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"! sockMgr.setName("Server"); // TO-DO: Need to change this to "Bidir"!
getTunnel().addSession(sockMgr.getSession()); getTunnel().addSession(sockMgr.getSession());
l.log("Ready!"); l.log("Ready!");
......
...@@ -192,6 +192,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn ...@@ -192,6 +192,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
* This constructor always starts the tunnel (ignoring the i2cp.delayOpen option). * This constructor always starts the tunnel (ignoring the i2cp.delayOpen option).
* It is used to add a client to an existing socket manager. * 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 * @param sockMgr the existing socket manager
*/ */
public I2PTunnelHTTPClient(int localPort, Logging l, I2PSocketManager sockMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) { 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 ...@@ -200,12 +203,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
// proxyList = new ArrayList(); // proxyList = new ArrayList();
setName("HTTP Proxy on " + getTunnel().listenHost + ':' + localPort); setName("HTTP Proxy on " + getTunnel().listenHost + ':' + localPort);
startRunning();
notifyEvent("openHTTPClientResult", "ok"); 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 * @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router * valid config to contact the router
*/ */
...@@ -216,10 +220,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn ...@@ -216,10 +220,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
_proxyNonce = Long.toString(_context.random().nextLong()); _proxyNonce = Long.toString(_context.random().nextLong());
//proxyList = new ArrayList(); // We won't use outside of i2p //proxyList = new ArrayList(); // We won't use outside of i2p
if(waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openHTTPClientResult", "error");
return;
}
if(wwwProxy != null) { if(wwwProxy != null) {
StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); StringTokenizer tok = new StringTokenizer(wwwProxy, ", ");
...@@ -229,9 +229,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn ...@@ -229,9 +229,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
} }
setName("HTTP Proxy on " + tunnel.listenHost + ':' + localPort); setName("HTTP Proxy on " + tunnel.listenHost + ':' + localPort);
startRunning();
notifyEvent("openHTTPClientResult", "ok"); notifyEvent("openHTTPClientResult", "ok");
} }
...@@ -611,6 +608,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn ...@@ -611,6 +608,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
_("i2paddresshelper cannot help you with a destination like that!") + _("i2paddresshelper cannot help you with a destination like that!") +
"</p>").getBytes("UTF-8")); "</p>").getBytes("UTF-8"));
writeFooter(out); writeFooter(out);
reader.drain();
// XXX: should closeSocket(s) be in a finally block? // XXX: should closeSocket(s) be in a finally block?
} catch (IOException ioe) { } catch (IOException ioe) {
// ignore // ignore
...@@ -725,7 +723,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn ...@@ -725,7 +723,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
out.write(getErrorPage("localhost", ERR_LOCALHOST).getBytes("UTF-8")); out.write(getErrorPage("localhost", ERR_LOCALHOST).getBytes("UTF-8"));
writeFooter(out); writeFooter(out);
reader.drain(); reader.drain();
s.close();
} catch (IOException ioe) { } catch (IOException ioe) {
// ignore // ignore
} finally { } finally {
......
...@@ -41,6 +41,9 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { ...@@ -41,6 +41,9 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase {
public static final String PROP_DCC = "i2ptunnel.ircclient.enableDCC"; 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 * @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 * @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router * valid config to contact the router
...@@ -81,8 +84,6 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { ...@@ -81,8 +84,6 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase {
_dccEnabled = Boolean.parseBoolean(tunnel.getClientOptions().getProperty(PROP_DCC)); _dccEnabled = Boolean.parseBoolean(tunnel.getClientOptions().getProperty(PROP_DCC));
// TODO add some prudent tunnel options (or is it too late?) // TODO add some prudent tunnel options (or is it too late?)
startRunning();
notifyEvent("openIRCClientResult", "ok"); notifyEvent("openIRCClientResult", "ok");
} }
......
...@@ -276,7 +276,7 @@ public class TunnelControllerGroup implements ClientApp { ...@@ -276,7 +276,7 @@ public class TunnelControllerGroup implements ClientApp {
for (int i = 0; i < _controllers.size(); i++) { for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = _controllers.get(i); TunnelController controller = _controllers.get(i);
if (controller.getStartOnLoad()) if (controller.getStartOnLoad())
controller.startTunnel(); controller.startTunnelBackground();
} }
} finally { } finally {
_controllersLock.readLock().unlock(); _controllersLock.readLock().unlock();
......
...@@ -109,6 +109,7 @@ public class DCCClientManager extends EventReceiver { ...@@ -109,6 +109,7 @@ public class DCCClientManager extends EventReceiver {
I2PTunnelDCCClient cTunnel = new I2PTunnelDCCClient(b32, localPort, port, l, sockMgr, I2PTunnelDCCClient cTunnel = new I2PTunnelDCCClient(b32, localPort, port, l, sockMgr,
_dispatch, _tunnel, ++_id); _dispatch, _tunnel, ++_id);
cTunnel.attachEventDispatcher(this); cTunnel.attachEventDispatcher(this);
cTunnel.startRunning();
int lport = cTunnel.getLocalPort(); int lport = cTunnel.getLocalPort();
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Opened client tunnel at port " + lport + _log.warn("Opened client tunnel at port " + lport +
......
...@@ -37,6 +37,9 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase { ...@@ -37,6 +37,9 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase {
public static final String CONNECT_STOP_EVENT = "connectionStopped"; 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 dest the target, presumably b32
* @param localPort if 0, use any port, get actual port selected with getLocalPort() * @param localPort if 0, use any port, get actual port selected with getLocalPort()
* @throws IllegalArgumentException if the I2PTunnel does not contain * @throws IllegalArgumentException if the I2PTunnel does not contain
...@@ -51,8 +54,6 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase { ...@@ -51,8 +54,6 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase {
_expires = tunnel.getContext().clock().now() + INBOUND_EXPIRE; _expires = tunnel.getContext().clock().now() + INBOUND_EXPIRE;
setName("DCC send -> " + dest + ':' + remotePort); setName("DCC send -> " + dest + ':' + remotePort);
startRunning();
} }
/** /**
......
...@@ -33,7 +33,12 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase { ...@@ -33,7 +33,12 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
// I2PSOCKSTunnel(localPort, l, ownDest, (EventDispatcher)null); // 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) { 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); super(localPort, ownDest, l, notifyThis, "SOCKS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel, pkf);
...@@ -44,8 +49,6 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase { ...@@ -44,8 +49,6 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
setName("SOCKS Proxy on " + tunnel.listenHost + ':' + localPort); setName("SOCKS Proxy on " + tunnel.listenHost + ':' + localPort);
parseOptions(); parseOptions();
startRunning();
notifyEvent("openSOCKSTunnelResult", "ok"); notifyEvent("openSOCKSTunnelResult", "ok");
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment