* I2PTunnel:

- Fix bug where delayed-open and close-on-idle tunnels would
        use a different tunnel pool instead of building their own
This commit is contained in:
zzz
2009-06-04 15:14:41 +00:00
parent ce23d76c72
commit 7e1e3c3c32
4 changed files with 58 additions and 56 deletions

View File

@ -44,6 +44,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
protected final Object sockLock = new Object(); // Guards sockMgr and mySockets protected final Object sockLock = new Object(); // Guards sockMgr and mySockets
protected I2PSocketManager sockMgr; // should be final and use a factory. LINT protected I2PSocketManager sockMgr; // should be final and use a factory. LINT
protected List mySockets = new ArrayList(); protected List mySockets = new ArrayList();
protected boolean _ownDest;
protected Destination dest = null; protected Destination dest = null;
private int localPort; private int localPort;
@ -114,6 +115,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
this.l = l; this.l = l;
this.handlerName = handlerName + _clientId; this.handlerName = handlerName + _clientId;
this.privKeyFile = pkf; this.privKeyFile = pkf;
_ownDest = ownDest; // == ! shared client
_context = tunnel.getContext(); _context = tunnel.getContext();
@ -129,13 +131,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
boolean openNow = !Boolean.valueOf(tunnel.getClientOptions().getProperty("i2cp.delayOpen")).booleanValue(); boolean openNow = !Boolean.valueOf(tunnel.getClientOptions().getProperty("i2cp.delayOpen")).booleanValue();
if (openNow) { if (openNow) {
while (sockMgr == null) { while (sockMgr == null) {
synchronized (sockLock) { verifySocketManager();
if (ownDest) {
sockMgr = buildSocketManager();
} else {
sockMgr = getSocketManager();
}
}
if (sockMgr == null) { if (sockMgr == null) {
_log.log(Log.CRIT, "Unable to create socket manager (our own? " + ownDest + ")"); _log.log(Log.CRIT, "Unable to create socket manager (our own? " + ownDest + ")");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {} try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
@ -209,27 +205,67 @@ 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
*/
protected void verifySocketManager() {
synchronized(sockLock) {
boolean newManager = false;
if (this.sockMgr == null) {
newManager = true;
} else {
I2PSession sess = sockMgr.getSession();
if (sess == null) {
newManager = true;
} else if (sess.isClosed() &&
Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.closeOnIdle")).booleanValue() &&
Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.newDestOnResume")).booleanValue()) {
// build a new socket manager and a new dest if the session is closed.
getTunnel().removeSession(sess);
if (_log.shouldLog(Log.WARN))
_log.warn(getTunnel().getClientOptions().getProperty("inbound.nickname") + ": Built a new destination on resume");
newManager = true;
} // else the old socket manager will reconnect the old session if necessary
}
if (newManager) {
if (_ownDest)
this.sockMgr = buildSocketManager();
else
this.sockMgr = getSocketManager();
}
}
}
/** this is ONLY for shared clients */
private static I2PSocketManager socketManager; private static I2PSocketManager socketManager;
/** this is ONLY for shared clients */
protected synchronized I2PSocketManager getSocketManager() { protected synchronized I2PSocketManager getSocketManager() {
return getSocketManager(getTunnel(), this.privKeyFile); return getSocketManager(getTunnel(), this.privKeyFile);
} }
/** this is ONLY for shared clients */
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) { protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
return getSocketManager(tunnel, null); return getSocketManager(tunnel, null);
} }
/** this is ONLY for shared clients */
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) { protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
if (socketManager != null) { if (socketManager != null) {
I2PSession s = socketManager.getSession(); I2PSession s = socketManager.getSession();
if ( (s == null) || (s.isClosed()) ) { if ( (s == null) || (s.isClosed()) ) {
_log.info("Building a new socket manager since the old one closed [s=" + s + "]"); if (_log.shouldLog(Log.INFO))
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since the old one closed [s=" + s + "]");
if (s != null) if (s != null)
tunnel.removeSession(s); tunnel.removeSession(s);
socketManager = buildSocketManager(tunnel, pkf); socketManager = buildSocketManager(tunnel, pkf);
} else { } else {
_log.info("Not building a new socket manager since the old one is open [s=" + s + "]"); if (_log.shouldLog(Log.INFO))
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Not building a new socket manager since the old one is open [s=" + s + "]");
} }
} else { } else {
_log.info("Building a new socket manager since there is no other one"); if (_log.shouldLog(Log.INFO))
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since there is no other one");
socketManager = buildSocketManager(tunnel, pkf); socketManager = buildSocketManager(tunnel, pkf);
} }
return socketManager; return socketManager;
@ -278,6 +314,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
} }
} }
sockManager.setName("Client"); 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()); tunnel.addSession(sockManager.getSession());
return sockManager; return sockManager;
} }
@ -343,12 +381,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* @return a new I2PSocket * @return a new I2PSocket
*/ */
public I2PSocket createI2PSocket(Destination dest) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException { public I2PSocket createI2PSocket(Destination dest) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException {
if (sockMgr == null) { verifySocketManager();
// we need this before getDefaultOptions()
synchronized(sockLock) {
sockMgr = getSocketManager();
}
}
return createI2PSocket(dest, getDefaultOptions()); return createI2PSocket(dest, getDefaultOptions());
} }
@ -369,22 +402,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
public I2PSocket createI2PSocket(Destination dest, I2PSocketOptions opt) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException { public I2PSocket createI2PSocket(Destination dest, I2PSocketOptions opt) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException {
I2PSocket i2ps; I2PSocket i2ps;
if (sockMgr == null) { verifySocketManager();
// delayed open - call get instead of build because the locking is up there
synchronized(sockLock) {
sockMgr = getSocketManager();
}
} else if (Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.closeOnIdle")).booleanValue() &&
Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.newDestOnResume")).booleanValue()) {
synchronized(sockLock) {
I2PSocketManager oldSockMgr = sockMgr;
// This will build a new socket manager and a new dest if the session is closed.
sockMgr = getSocketManager();
if (oldSockMgr != sockMgr) {
_log.warn("Built a new destination on resume");
}
}
} // else the old socket manager will reconnect the old session if necessary
i2ps = sockMgr.connect(dest, opt); i2ps = sockMgr.connect(dest, opt);
synchronized (sockLock) { synchronized (sockLock) {
mySockets.add(i2ps); mySockets.add(i2ps);

View File

@ -157,11 +157,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
if (!defaultOpts.contains("i2p.streaming.inactivityTimeout")) if (!defaultOpts.contains("i2p.streaming.inactivityTimeout"))
defaultOpts.setProperty("i2p.streaming.inactivityTimeout", ""+DEFAULT_READ_TIMEOUT); defaultOpts.setProperty("i2p.streaming.inactivityTimeout", ""+DEFAULT_READ_TIMEOUT);
// delayed start // delayed start
if (sockMgr == null) { verifySocketManager();
synchronized(sockLock) {
sockMgr = getSocketManager();
}
}
I2PSocketOptions opts = sockMgr.buildOptions(defaultOpts); I2PSocketOptions opts = sockMgr.buildOptions(defaultOpts);
if (!defaultOpts.containsKey(I2PSocketOptions.PROP_CONNECT_TIMEOUT)) if (!defaultOpts.containsKey(I2PSocketOptions.PROP_CONNECT_TIMEOUT))
opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT); opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);

View File

@ -211,11 +211,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (!defaultOpts.contains("i2p.streaming.inactivityTimeout")) if (!defaultOpts.contains("i2p.streaming.inactivityTimeout"))
defaultOpts.setProperty("i2p.streaming.inactivityTimeout", ""+DEFAULT_READ_TIMEOUT); defaultOpts.setProperty("i2p.streaming.inactivityTimeout", ""+DEFAULT_READ_TIMEOUT);
// delayed start // delayed start
if (sockMgr == null) { verifySocketManager();
synchronized(sockLock) {
sockMgr = getSocketManager();
}
}
I2PSocketOptions opts = sockMgr.buildOptions(defaultOpts); I2PSocketOptions opts = sockMgr.buildOptions(defaultOpts);
if (!defaultOpts.containsKey(I2PSocketOptions.PROP_CONNECT_TIMEOUT)) if (!defaultOpts.containsKey(I2PSocketOptions.PROP_CONNECT_TIMEOUT))
opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT); opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);

View File

@ -778,12 +778,6 @@ public class IndexBean {
config.setProperty("interface", _reachableByOther); config.setProperty("interface", _reachableByOther);
else else
config.setProperty("interface", _reachableBy); config.setProperty("interface", _reachableBy);
config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
if (_name != null && !_sharedClient) {
config.setProperty("option.inbound.nickname", _name);
config.setProperty("option.outbound.nickname", _name);
}
config.setProperty("sharedClient", _sharedClient + ""); config.setProperty("sharedClient", _sharedClient + "");
for (String p : _booleanClientOpts) for (String p : _booleanClientOpts)
config.setProperty("option." + p, "" + _booleanOptions.contains(p)); config.setProperty("option." + p, "" + _booleanOptions.contains(p));
@ -896,14 +890,12 @@ public class IndexBean {
config.setProperty("option.i2p.streaming.connectDelay", "1000"); config.setProperty("option.i2p.streaming.connectDelay", "1000");
else else
config.setProperty("option.i2p.streaming.connectDelay", "0"); config.setProperty("option.i2p.streaming.connectDelay", "0");
if (_name != null) { if (isClient(_type) && _sharedClient) {
if ( (!isClient(_type)) || (!_sharedClient) ) { config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
config.setProperty("option.inbound.nickname", _name); config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
config.setProperty("option.outbound.nickname", _name); } else if (_name != null) {
} else { config.setProperty("option.inbound.nickname", _name);
config.setProperty("option.inbound.nickname", CLIENT_NICKNAME); config.setProperty("option.outbound.nickname", _name);
config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
}
} }
if ("interactive".equals(_profile)) if ("interactive".equals(_profile))
// This was 1 which doesn't make much sense // This was 1 which doesn't make much sense