* 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:
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user