i2ptunnel: Fix shutdown of client tunnels on server socket errors,

broken in fix for ticket #815
TCG still doesn't go back to stopped, to be fixed.
Test case: configure low port.
This commit is contained in:
zzz
2015-04-24 19:19:18 +00:00
parent 81ad33d9e3
commit 08e96109a7
2 changed files with 34 additions and 19 deletions

View File

@@ -506,9 +506,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_log.debug("startup " + _clientId, new Exception("I did it")); _log.debug("startup " + _clientId, new Exception("I did it"));
// prevent JVM exit when running outside the router // prevent JVM exit when running outside the router
boolean isDaemon = getTunnel().getContext().isRouterContext(); boolean isDaemon = getTunnel().getContext().isRouterContext();
open = true;
Thread t = new I2PAppThread(this, "I2PTunnel Client " + getTunnel().listenHost + ':' + localPort, isDaemon); Thread t = new I2PAppThread(this, "I2PTunnel Client " + getTunnel().listenHost + ':' + localPort, isDaemon);
t.start(); t.start();
open = true;
synchronized (this) { synchronized (this) {
while (!listenerReady && open) { while (!listenerReady && open) {
try { try {
@@ -638,18 +638,21 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
/** /**
* Non-final since 0.9.11. * Non-final since 0.9.11.
* Any overrides must set listenerReady = true. * open will be true before being called.
* Any overrides must set listenerReady = true and then notifyAll() if setup is successful,
* and must call close() and then notifyAll() on failure or termination.
*/ */
public void run() { public void run() {
try { InetAddress addr = getListenHost(l);
InetAddress addr = getListenHost(l); if (addr == null) {
if (addr == null) { close(true);
open = false; open = false;
synchronized (this) { synchronized (this) {
notifyAll(); notifyAll();
}
return;
} }
return;
}
try {
Properties opts = getTunnel().getClientOptions(); Properties opts = getTunnel().getClientOptions();
boolean useSSL = Boolean.parseBoolean(opts.getProperty(PROP_USE_SSL)); boolean useSSL = Boolean.parseBoolean(opts.getProperty(PROP_USE_SSL));
if (useSSL) { if (useSSL) {
@@ -681,7 +684,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
// Notify constructor that port is ready // Notify constructor that port is ready
synchronized (this) { synchronized (this) {
listenerReady = true; listenerReady = true;
notify(); notifyAll();
} }
// Wait until we are authorized to process data // Wait until we are authorized to process data
@@ -709,14 +712,14 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
manageConnection(s); manageConnection(s);
} }
} catch (IOException ex) { } catch (IOException ex) {
if (open) {
_log.error("Error listening for connections on " + localPort, ex);
notifyEvent("openBaseClientResult", "error");
}
synchronized (sockLock) { synchronized (sockLock) {
mySockets.clear(); mySockets.clear();
} }
open = false; if (open) {
_log.error("Error listening for connections on " + addr + " port " + localPort, ex);
notifyEvent("openBaseClientResult", "error");
close(true);
}
synchronized (this) { synchronized (this) {
notifyAll(); notifyAll();
} }
@@ -766,6 +769,18 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
} }
} }
/**
* Note that the tunnel can be reopened after this by calling startRunning().
* This may not release all resources. In particular, the I2PSocketManager remains
* and it may have timer threads that continue running.
*
* To release all resources permanently, call destroy().
*
* Does nothing if open is already false.
* Sets open = false but does not notifyAll().
*
* @return success
*/
public boolean close(boolean forced) { public boolean close(boolean forced) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("close() called: forced = " + forced + " open = " + open + " sockMgr = " + sockMgr); _log.info("close() called: forced = " + forced + " open = " + open + " sockMgr = " + sockMgr);
@@ -801,8 +816,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
try { try {
if (ss != null) ss.close(); if (ss != null) ss.close();
} catch (IOException ex) { } catch (IOException ex) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldDebug())
_log.warn("error closing", ex); _log.debug("error closing", ex);
return false; return false;
} }
//l.log("Client closed."); //l.log("Client closed.");

View File

@@ -67,7 +67,7 @@ public class I2Ping extends I2PTunnelClientBase {
// Notify constructor that port is ready // Notify constructor that port is ready
synchronized (this) { synchronized (this) {
listenerReady = true; listenerReady = true;
notify(); notifyAll();
} }
l.log("*** I2Ping results:"); l.log("*** I2Ping results:");
try { try {