forked from I2P_Developers/i2p.i2p
* 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)
This commit is contained in:
@ -1,5 +1,7 @@
|
|||||||
package net.i2p.client.streaming;
|
package net.i2p.client.streaming;
|
||||||
|
|
||||||
|
import java.net.ConnectException;
|
||||||
|
|
||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,13 +19,16 @@ public interface I2PServerSocket {
|
|||||||
* connection and the local application wasn't .accept()ing new connections,
|
* connection and the local application wasn't .accept()ing new connections,
|
||||||
* they should get refused (if .accept() doesnt occur in some small period)
|
* 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
|
* @throws I2PException if there is a problem with reading a new socket
|
||||||
* from the data available (aka the I2PSession closed, etc)
|
* 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
|
* Access the manager which is coordinating the server socket
|
||||||
*/
|
*/
|
||||||
public I2PSocketManager getManager();
|
public I2PSocketManager getManager();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.i2p.client.streaming;
|
package net.i2p.client.streaming;
|
||||||
|
|
||||||
|
import java.net.ConnectException;
|
||||||
|
|
||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
@ -12,42 +14,61 @@ class I2PServerSocketImpl implements I2PServerSocket {
|
|||||||
private I2PSocketManager mgr;
|
private I2PSocketManager mgr;
|
||||||
private I2PSocket cached = null; // buffer one socket here
|
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) {
|
public I2PServerSocketImpl(I2PSocketManager mgr) {
|
||||||
this.mgr = mgr;
|
this.mgr = mgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized I2PSocket accept() throws I2PException {
|
public synchronized I2PSocket accept() throws I2PException, ConnectException {
|
||||||
while (cached == null) {
|
I2PSocket ret;
|
||||||
myWait();
|
|
||||||
}
|
synchronized (acceptLock) {
|
||||||
I2PSocket ret = cached;
|
while ((cached == null) && !closing) {
|
||||||
cached = null;
|
myWait();
|
||||||
notifyAll();
|
}
|
||||||
|
|
||||||
|
if (closing) {
|
||||||
|
throw new ConnectException("I2PServerSocket closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cached;
|
||||||
|
cached = null;
|
||||||
|
acceptLock.notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
_log.debug("TIMING: handed out accept result " + ret.hashCode());
|
_log.debug("TIMING: handed out accept result " + ret.hashCode());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean getNewSocket(I2PSocket s) {
|
public boolean getNewSocket(I2PSocket s) {
|
||||||
while (cached != null) {
|
synchronized (acceptLock) {
|
||||||
myWait();
|
while (cached != null) {
|
||||||
}
|
myWait();
|
||||||
cached = s;
|
}
|
||||||
notifyAll();
|
cached = s;
|
||||||
|
acceptLock.notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws I2PException {
|
public void close() throws I2PException {
|
||||||
//noop
|
synchronized (acceptLock) {
|
||||||
}
|
closing = true;
|
||||||
|
acceptLock.notifyAll();
|
||||||
private void myWait() {
|
}
|
||||||
try {
|
|
||||||
wait();
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public I2PSocketManager getManager() {
|
public I2PSocketManager getManager() {
|
||||||
return mgr;
|
return mgr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private void myWait() {
|
||||||
|
try {
|
||||||
|
acceptLock.wait();
|
||||||
|
} catch (InterruptedException ex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user