First step for the "connection refused" concept: incoming connections

won't be accepted until the server app actually requires an I2PServerSocket
from the I2PSocketManager.
It allows both to add a little bit of functionality, and to fix a nasty bug: it
was possible to hang an app that connects through the I2PSocketManager but
actually doesn't accept() connections (if 2 connection requests were sent
to the app, the I2PSocketManager got stuck waiting forever on
I2PServerSocketImpl.getNewSocket()).
This commit is contained in:
human
2004-04-16 03:31:13 +00:00
committed by zzz
parent 2a619f3fba
commit 031338d84d
2 changed files with 34 additions and 12 deletions

View File

@ -63,7 +63,7 @@ class I2PSocketImpl implements I2PSocket {
public String getRemoteID(boolean wait, long maxWait) throws InterruptedIOException {
long dieAfter = System.currentTimeMillis() + maxWait;
synchronized (remoteIDWaiter) {
while (wait && remoteID == null) {
if (wait) {
try {
if (maxWait > 0)
remoteIDWaiter.wait(maxWait);
@ -74,8 +74,7 @@ class I2PSocketImpl implements I2PSocket {
if ((maxWait > 0) && (System.currentTimeMillis() > dieAfter))
throw new InterruptedIOException("Timed out waiting for remote ID");
}
if (wait) {
_log.debug("TIMING: RemoteID set to " + I2PSocketManager.getReadableForm(remoteID) + " for "
+ this.hashCode());
}

View File

@ -31,7 +31,7 @@ import net.i2p.util.Log;
public class I2PSocketManager implements I2PSessionListener {
private final static Log _log = new Log(I2PSocketManager.class);
private I2PSession _session;
private I2PServerSocketImpl _serverSocket;
private I2PServerSocketImpl _serverSocket = null;
private Object lock = new Object(); // for locking socket lists
private HashMap _outSockets;
private HashMap _inSockets;
@ -41,7 +41,6 @@ public class I2PSocketManager implements I2PSessionListener {
public I2PSocketManager() {
_session = null;
_serverSocket = new I2PServerSocketImpl(this);
_inSockets = new HashMap(16);
_outSockets = new HashMap(16);
}
@ -106,14 +105,19 @@ public class I2PSocketManager implements I2PSessionListener {
_log.debug("*Disconnect outgoing!");
try {
s = (I2PSocketImpl) _outSockets.get(id);
if (payload.length == 0 && s != null) {
if (s != null) {
if (payload.length > 0) {
_log.debug("Disconnect packet had "
+ payload.length + " bytes");
}
if (s.getRemoteID(false) == null) {
s.setRemoteID(null); // Just to wake up socket
return;
}
s.internalClose();
_outSockets.remove(id);
return;
} else {
if (payload.length > 0) _log.warn("Disconnect packet had " + payload.length + " bytes");
return;
}
return;
} catch (Exception t) {
_log.error("Ignoring error on disconnect", t);
}
@ -136,6 +140,20 @@ public class I2PSocketManager implements I2PSessionListener {
Destination d = new Destination();
d.readBytes(new ByteArrayInputStream(payload));
if (_serverSocket == null) {
// The app did not instantiate an I2PServerSocket
byte[] packet = makePacket((byte) 0x52, id, newLocalID.getBytes("ISO-8859-1"));
boolean replySentOk = false;
synchronized (_session) {
replySentOk = _session.sendMessage(d, packet);
}
if (!replySentOk) {
_log.error("Error sending close to " + d.calculateHash().toBase64()
+ " in response to a new con message", new Exception("Failed creation"));
}
return;
}
s = new I2PSocketImpl(d, this, false, newLocalID);
s.setRemoteID(id);
if (_serverSocket.getNewSocket(s)) {
@ -227,6 +245,9 @@ public class I2PSocketManager implements I2PSessionListener {
}
public I2PServerSocket getServerSocket() {
if (_serverSocket == null) {
_serverSocket = new I2PServerSocketImpl(this);
}
return _serverSocket;
}
@ -262,6 +283,7 @@ public class I2PSocketManager implements I2PSessionListener {
throw new I2PException("Unable to reach peer");
}
remoteID = s.getRemoteID(true, options.getConnectTimeout());
if (remoteID == null) { throw new I2PException("Peer refused connection"); }
if ("".equals(remoteID)) { throw new I2PException("Unable to reach peer"); }
_log.debug("TIMING: s given out for remoteID " + getReadableForm(remoteID));
return s;
@ -326,6 +348,7 @@ public class I2PSocketManager implements I2PSessionListener {
public static String getReadableForm(String id) {
try {
if (id == null) return "(null)";
if (id.length() != 3) return "Bogus";
return Base64.encode(id.getBytes("ISO-8859-1"));
} catch (UnsupportedEncodingException ex) {