From d2b09ecfdaa39507ce32480cdbad07521a8de272 Mon Sep 17 00:00:00 2001
From: human <human>
Date: Wed, 14 Apr 2004 15:28:02 +0000
Subject: [PATCH] * Fixed race that (maybe) caused the problems reported by aum
 on   <http://dev.i2p.net/pipermail/i2p/2004-April/000214.html>; * slightly
 revised locking; * made accept() throw a ConnectException when the
 I2PServerSocket is closed. (human)

---
 .../i2p/client/streaming/I2PServerSocket.java |  9 ++-
 .../client/streaming/I2PServerSocketImpl.java | 65 ++++++++++++-------
 2 files changed, 50 insertions(+), 24 deletions(-)

diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java
index 6f46364d63..726d462ceb 100644
--- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocket.java
@@ -1,5 +1,7 @@
 package net.i2p.client.streaming;
 
+import java.net.ConnectException;
+
 import net.i2p.I2PException;
 
 /**
@@ -17,13 +19,16 @@ public interface I2PServerSocket {
      * connection and the local application wasn't .accept()ing new connections,
      * they should get refused (if .accept() doesnt occur in some small period)
      *
+     * @return a connected I2PSocket
+     *
      * @throws I2PException if there is a problem with reading a new socket
      *         from the data available (aka the I2PSession closed, etc)
+     * @throws ConnectException if the I2PServerSocket is closed
      */
-    public I2PSocket accept() throws I2PException;
+    public I2PSocket accept() throws I2PException, ConnectException;
 
     /**
      * Access the manager which is coordinating the server socket
      */
     public I2PSocketManager getManager();
-}
\ No newline at end of file
+}
diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
index 102a84af2a..fc89437bd0 100644
--- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
@@ -1,5 +1,7 @@
 package net.i2p.client.streaming;
 
+import java.net.ConnectException;
+
 import net.i2p.I2PException;
 import net.i2p.util.Log;
 
@@ -12,42 +14,61 @@ class I2PServerSocketImpl implements I2PServerSocket {
     private I2PSocketManager mgr;
     private I2PSocket cached = null; // buffer one socket here
 
+    private boolean closing = false; // Are we being closed?
+
+    private Object acceptLock = new Object();
+
     public I2PServerSocketImpl(I2PSocketManager mgr) {
         this.mgr = mgr;
     }
 
-    public synchronized I2PSocket accept() throws I2PException {
-        while (cached == null) {
-            myWait();
-        }
-        I2PSocket ret = cached;
-        cached = null;
-        notifyAll();
+    public synchronized I2PSocket accept() throws I2PException, ConnectException {
+	I2PSocket ret;
+	
+	synchronized (acceptLock) {
+	    while ((cached == null) && !closing) {
+		myWait();
+	    }
+
+	    if (closing) {
+		throw new ConnectException("I2PServerSocket closed");
+	    }
+
+	    ret = cached;
+	    cached = null;
+	    acceptLock.notifyAll();
+	}
+	
         _log.debug("TIMING: handed out accept result " + ret.hashCode());
         return ret;
     }
 
-    public synchronized boolean getNewSocket(I2PSocket s) {
-        while (cached != null) {
-            myWait();
-        }
-        cached = s;
-        notifyAll();
+    public boolean getNewSocket(I2PSocket s) {
+	synchronized (acceptLock) {
+	    while (cached != null) {
+		myWait();
+	    }
+	    cached = s;
+	    acceptLock.notifyAll();
+	}
+
         return true;
     }
 
     public void close() throws I2PException {
-        //noop
-    }
-
-    private void myWait() {
-        try {
-            wait();
-        } catch (InterruptedException ex) {
-        }
+	synchronized (acceptLock) {
+	    closing = true;
+	    acceptLock.notifyAll();
+	}
     }
 
     public I2PSocketManager getManager() {
         return mgr;
     }
-}
\ No newline at end of file
+
+    private void myWait() {
+	try {
+	    acceptLock.wait();
+	} catch (InterruptedException ex) {}
+    }
+}
-- 
GitLab