From 60aa8c57a446d9c94986658aaafcda6db5b64139 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Sun, 24 Nov 2013 23:42:53 +0000
Subject: [PATCH] I2PTunnel: Fix a shared client configured with
 i2cp.newDestOnResume not restarting correctly, caused by previous checkin

---
 .../src/net/i2p/i2ptunnel/I2PTunnelClientBase.java | 14 +++++++++++---
 .../net/i2p/client/streaming/I2PSocketManager.java |  8 ++++++++
 .../i2p/client/streaming/I2PSocketManagerFull.java |  9 +++++++++
 router/java/src/net/i2p/router/RouterVersion.java  |  2 +-
 4 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
index 2ba6acc11f..bea24ee104 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
@@ -252,7 +252,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
     protected void verifySocketManager() {
         synchronized(sockLock) {
             boolean newManager = false;
-            if (this.sockMgr == null) {
+            // other shared client could have destroyed it
+            if (this.sockMgr == null || this.sockMgr.isDestroyed()) {
                 newManager = true;
             } else {
                 I2PSession sess = sockMgr.getSession();
@@ -264,7 +265,14 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
                     if (_log.shouldLog(Log.WARN))
                         _log.warn(getTunnel().getClientOptions().getProperty("inbound.nickname") + ": Built a new destination on resume");
                     // make sure the old one is closed
-                    sockMgr.destroySocketManager();
+                    // if it's shared client, it will be destroyed in getSocketManager()
+                    // with the correct locking
+                    boolean shouldDestroy;
+                    synchronized(I2PTunnelClientBase.class) {
+                        shouldDestroy = sockMgr != socketManager;
+                    }
+                    if (shouldDestroy)
+                        sockMgr.destroySocketManager();
                     newManager = true;
                 }  // else the old socket manager will reconnect the old session if necessary
             }
@@ -316,7 +324,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
     protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
         // shadows instance _log
         Log _log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
-        if (socketManager != null) {
+        if (socketManager != null && !socketManager.isDestroyed()) {
             I2PSession s = socketManager.getSession();
             if (s.isClosed()) {
                 if (_log.shouldLog(Log.INFO))
diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManager.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManager.java
index 236a2b32cd..8a8aa4e4db 100644
--- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManager.java
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManager.java
@@ -104,8 +104,16 @@ public interface I2PSocketManager {
      * Destroy the socket manager, freeing all the associated resources.  This
      * method will block untill all the managed sockets are closed.
      *
+     * The socket manager CANNOT be reused after this.
      */
     public void destroySocketManager();
+    
+    /**
+     * Has the socket manager been destroyed?
+     *
+     * @since 0.9.9
+     */
+    public boolean isDestroyed();
 
     /**
      * Retrieve a set of currently connected I2PSockets, either initiated locally or remotely.
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
index 4dcc81e04f..0d06597570 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
@@ -338,6 +338,15 @@ public class I2PSocketManagerFull implements I2PSocketManager {
         }
     }
 
+    /**
+     * Has the socket manager been destroyed?
+     *
+     * @since 0.9.9
+     */
+    public boolean isDestroyed() {
+        return _isDestroyed.get();
+    }
+
     /**
      * Retrieve a set of currently connected I2PSockets, either initiated locally or remotely.
      *
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index a06babd519..98bd96d4ed 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
     /** deprecated */
     public final static String ID = "Monotone";
     public final static String VERSION = CoreVersion.VERSION;
-    public final static long BUILD = 31;
+    public final static long BUILD = 32;
 
     /** for example "-test" */
     public final static String EXTRA = "-rc";
-- 
GitLab