various tweaks to make sure we release appropriate references ASAP
This commit is contained in:
@ -331,6 +331,7 @@ public class Connection {
|
|||||||
_outboundPackets.clear();
|
_outboundPackets.clear();
|
||||||
_outboundPackets.notifyAll();
|
_outboundPackets.notifyAll();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (removeFromConMgr) {
|
if (removeFromConMgr) {
|
||||||
if (!_disconnectScheduled) {
|
if (!_disconnectScheduled) {
|
||||||
_disconnectScheduled = true;
|
_disconnectScheduled = true;
|
||||||
@ -338,10 +339,25 @@ public class Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void disconnectComplete() {
|
void disconnectComplete() {
|
||||||
_connected = false;
|
_connected = false;
|
||||||
|
if (_socket != null)
|
||||||
|
_socket.destroy();
|
||||||
|
_socket = null;
|
||||||
|
_inputStream = null;
|
||||||
|
if (_outputStream != null)
|
||||||
|
_outputStream.destroy();
|
||||||
|
_outputStream = null;
|
||||||
|
_outboundQueue = null;
|
||||||
|
_handler = null;
|
||||||
|
if (_receiver != null)
|
||||||
|
_receiver.destroy();
|
||||||
|
_receiver = null;
|
||||||
|
if (_activityTimer != null)
|
||||||
|
SimpleTimer.getInstance().addEvent(_activityTimer, 1);
|
||||||
|
_activityTimer = null;
|
||||||
|
|
||||||
if (!_disconnectScheduled) {
|
if (!_disconnectScheduled) {
|
||||||
_disconnectScheduled = true;
|
_disconnectScheduled = true;
|
||||||
|
|
||||||
@ -539,6 +555,7 @@ public class Connection {
|
|||||||
|
|
||||||
private void resetActivityTimer() {
|
private void resetActivityTimer() {
|
||||||
if (_options.getInactivityTimeout() <= 0) return;
|
if (_options.getInactivityTimeout() <= 0) return;
|
||||||
|
if (_activityTimer == null) return;
|
||||||
long howLong = _activityTimer.getTimeLeft();
|
long howLong = _activityTimer.getTimeLeft();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Resetting the inactivity timer to " + howLong);
|
_log.debug("Resetting the inactivity timer to " + howLong);
|
||||||
@ -617,12 +634,15 @@ public class Connection {
|
|||||||
buf.append("] ");
|
buf.append("] ");
|
||||||
}
|
}
|
||||||
buf.append("unacked inbound? ").append(getUnackedPacketsReceived());
|
buf.append("unacked inbound? ").append(getUnackedPacketsReceived());
|
||||||
buf.append(" [high ").append(_inputStream.getHighestBlockId());
|
if (_inputStream != null) {
|
||||||
|
buf.append(" [high ");
|
||||||
|
buf.append(_inputStream.getHighestBlockId());
|
||||||
long nacks[] = _inputStream.getNacks();
|
long nacks[] = _inputStream.getNacks();
|
||||||
if (nacks != null)
|
if (nacks != null)
|
||||||
for (int i = 0; i < nacks.length; i++)
|
for (int i = 0; i < nacks.length; i++)
|
||||||
buf.append(" ").append(nacks[i]);
|
buf.append(" ").append(nacks[i]);
|
||||||
buf.append("]");
|
buf.append("]");
|
||||||
|
}
|
||||||
buf.append("]");
|
buf.append("]");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
@ -127,4 +127,8 @@ class ConnectionDataReceiver implements MessageOutputStream.DataReceiver {
|
|||||||
public final boolean writeFailed() { return false; }
|
public final boolean writeFailed() { return false; }
|
||||||
public final boolean writeSuccessful() { return true; }
|
public final boolean writeSuccessful() { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
_connection = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class ConnectionManager {
|
|||||||
_conPacketHandler = new ConnectionPacketHandler(context);
|
_conPacketHandler = new ConnectionPacketHandler(context);
|
||||||
_session = session;
|
_session = session;
|
||||||
session.setSessionListener(_messageHandler);
|
session.setSessionListener(_messageHandler);
|
||||||
_outboundQueue = new PacketQueue(context, session);
|
_outboundQueue = new PacketQueue(context, session, this);
|
||||||
_allowIncoming = false;
|
_allowIncoming = false;
|
||||||
_maxConcurrentStreams = maxConcurrent;
|
_maxConcurrentStreams = maxConcurrent;
|
||||||
_numWaiting = 0;
|
_numWaiting = 0;
|
||||||
@ -102,11 +102,12 @@ public class ConnectionManager {
|
|||||||
reject = true;
|
reject = true;
|
||||||
} else {
|
} else {
|
||||||
while (true) {
|
while (true) {
|
||||||
Connection oldCon = (Connection)_connectionByInboundId.put(new ByteArray(receiveId), con);
|
ByteArray ba = new ByteArray(receiveId);
|
||||||
|
Connection oldCon = (Connection)_connectionByInboundId.put(ba, con);
|
||||||
if (oldCon == null) {
|
if (oldCon == null) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
_connectionByInboundId.put(new ByteArray(receiveId), oldCon);
|
_connectionByInboundId.put(ba, oldCon);
|
||||||
// receiveId already taken, try another
|
// receiveId already taken, try another
|
||||||
_context.random().nextBytes(receiveId);
|
_context.random().nextBytes(receiveId);
|
||||||
}
|
}
|
||||||
@ -210,15 +211,19 @@ public class ConnectionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean locked_tooManyStreams() {
|
private boolean locked_tooManyStreams() {
|
||||||
if (_maxConcurrentStreams <= 0) return false;
|
|
||||||
if (_connectionByInboundId.size() < _maxConcurrentStreams) return false;
|
|
||||||
|
|
||||||
int active = 0;
|
int active = 0;
|
||||||
for (Iterator iter = _connectionByInboundId.values().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = _connectionByInboundId.values().iterator(); iter.hasNext(); ) {
|
||||||
Connection con = (Connection)iter.next();
|
Connection con = (Connection)iter.next();
|
||||||
if (con.getIsConnected())
|
if (con.getIsConnected())
|
||||||
active++;
|
active++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( (_connectionByInboundId.size() > 100) && (_log.shouldLog(Log.INFO)) )
|
||||||
|
_log.info("More than 100 connections! " + active
|
||||||
|
+ " total: " + _connectionByInboundId.size());
|
||||||
|
|
||||||
|
if (_maxConcurrentStreams <= 0) return false;
|
||||||
|
if (_connectionByInboundId.size() < _maxConcurrentStreams) return false;
|
||||||
return (active >= _maxConcurrentStreams);
|
return (active >= _maxConcurrentStreams);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,8 +250,15 @@ public class ConnectionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeConnection(Connection con) {
|
public void removeConnection(Connection con) {
|
||||||
|
boolean removed = false;
|
||||||
synchronized (_connectionLock) {
|
synchronized (_connectionLock) {
|
||||||
_connectionByInboundId.remove(new ByteArray(con.getReceiveStreamId()));
|
Object o = _connectionByInboundId.remove(new ByteArray(con.getReceiveStreamId()));
|
||||||
|
removed = (o == con);
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("Connection removed? " + removed + " remaining: "
|
||||||
|
+ _connectionByInboundId.size() + ": " + con);
|
||||||
|
if (!removed && _log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("Failed to remove " + con +"\n" + _connectionByInboundId.values());
|
||||||
_connectionLock.notifyAll();
|
_connectionLock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,12 @@ public class ConnectionPacketHandler {
|
|||||||
con.getOptions().setChoke(0);
|
con.getOptions().setChoke(0);
|
||||||
boolean isNew = con.getInputStream().messageReceived(packet.getSequenceNum(), packet.getPayload());
|
boolean isNew = con.getInputStream().messageReceived(packet.getSequenceNum(), packet.getPayload());
|
||||||
|
|
||||||
|
if ( (packet.getSequenceNum() == 0) && (packet.getPayloadSize() > 0) ) {
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("seq=0 && size=" + packet.getPayloadSize() + ": isNew? " + isNew
|
||||||
|
+ " packet: " + packet + " con: " + con);
|
||||||
|
}
|
||||||
|
|
||||||
// close *after* receiving the data, as well as after verifying the signatures / etc
|
// close *after* receiving the data, as well as after verifying the signatures / etc
|
||||||
if (packet.isFlagSet(Packet.FLAG_CLOSE) && packet.isFlagSet(Packet.FLAG_SIGNATURE_INCLUDED))
|
if (packet.isFlagSet(Packet.FLAG_CLOSE) && packet.isFlagSet(Packet.FLAG_SIGNATURE_INCLUDED))
|
||||||
con.closeReceived();
|
con.closeReceived();
|
||||||
@ -289,6 +295,8 @@ public class ConnectionPacketHandler {
|
|||||||
}
|
}
|
||||||
public void timeReached() {
|
public void timeReached() {
|
||||||
if (_con.getLastSendTime() <= _created) {
|
if (_con.getLastSendTime() <= _created) {
|
||||||
|
if (!_con.getIsConnected()) return;
|
||||||
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Last sent was a while ago, and we want to ack a dup");
|
_log.debug("Last sent was a while ago, and we want to ack a dup");
|
||||||
// we haven't done anything since receiving the dup, send an
|
// we haven't done anything since receiving the dup, send an
|
||||||
|
@ -19,12 +19,14 @@ public class I2PSocketFull implements I2PSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
|
if (_connection == null) return;
|
||||||
if (_connection.getIsConnected()) {
|
if (_connection.getIsConnected()) {
|
||||||
_connection.getOutputStream().close();
|
_connection.getOutputStream().close();
|
||||||
_connection.disconnect(true);
|
_connection.disconnect(true);
|
||||||
} else {
|
} else {
|
||||||
//throw new IOException("Not connected");
|
//throw new IOException("Not connected");
|
||||||
}
|
}
|
||||||
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
@ -65,4 +67,9 @@ public class I2PSocketFull implements I2PSocket {
|
|||||||
public void setSocketErrorListener(I2PSocket.SocketErrorListener lsnr) {
|
public void setSocketErrorListener(I2PSocket.SocketErrorListener lsnr) {
|
||||||
_listener = lsnr;
|
_listener = lsnr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
_connection = null;
|
||||||
|
_listener = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,8 @@ public class I2PSocketManagerFull implements I2PSocketManager {
|
|||||||
throws I2PException, NoRouteToHostException {
|
throws I2PException, NoRouteToHostException {
|
||||||
if (_connectionManager.getSession().isClosed())
|
if (_connectionManager.getSession().isClosed())
|
||||||
throw new I2PException("Session is closed");
|
throw new I2PException("Session is closed");
|
||||||
|
if (options == null)
|
||||||
|
options = _defaultOptions;
|
||||||
ConnectionOptions opts = null;
|
ConnectionOptions opts = null;
|
||||||
if (options instanceof ConnectionOptions)
|
if (options instanceof ConnectionOptions)
|
||||||
opts = (ConnectionOptions)options;
|
opts = (ConnectionOptions)options;
|
||||||
|
@ -198,6 +198,10 @@ public class MessageOutputStream extends OutputStream {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
_dataReceiver = null;
|
||||||
|
}
|
||||||
|
|
||||||
public interface DataReceiver {
|
public interface DataReceiver {
|
||||||
/**
|
/**
|
||||||
* Nonblocking write
|
* Nonblocking write
|
||||||
|
@ -105,11 +105,12 @@ public class PacketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final SimpleDateFormat _fmt = new SimpleDateFormat("hh:mm:ss.SSS");
|
private static final SimpleDateFormat _fmt = new SimpleDateFormat("hh:mm:ss.SSS");
|
||||||
static void displayPacket(Packet packet, String prefix) {
|
void displayPacket(Packet packet, String prefix) {
|
||||||
String msg = null;
|
String msg = null;
|
||||||
synchronized (_fmt) {
|
synchronized (_fmt) {
|
||||||
msg = _fmt.format(new Date()) + ": " + prefix + " " + packet.toString();
|
msg = _fmt.format(new Date()) + ": " + prefix + " " + packet.toString();
|
||||||
}
|
}
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
System.out.println(msg);
|
System.out.println(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,12 +77,14 @@ public class PacketLocal extends Packet implements MessageOutputStream.WriteStat
|
|||||||
_ackOn = _context.clock().now();
|
_ackOn = _context.clock().now();
|
||||||
notifyAll();
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
_connection = null;
|
||||||
}
|
}
|
||||||
public void cancelled() {
|
public void cancelled() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
_cancelledOn = _context.clock().now();
|
_cancelledOn = _context.clock().now();
|
||||||
notifyAll();
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
_connection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** how long after packet creation was it acked? */
|
/** how long after packet creation was it acked? */
|
||||||
@ -113,9 +115,11 @@ public class PacketLocal extends Packet implements MessageOutputStream.WriteStat
|
|||||||
_acceptedOn = _context.clock().now();
|
_acceptedOn = _context.clock().now();
|
||||||
else
|
else
|
||||||
_acceptedOn = -1;
|
_acceptedOn = -1;
|
||||||
|
_connection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForCompletion(int maxWaitMs) {
|
public void waitForCompletion(int maxWaitMs) {
|
||||||
|
_connection = null;
|
||||||
long expiration = _context.clock().now()+maxWaitMs;
|
long expiration = _context.clock().now()+maxWaitMs;
|
||||||
while (true) {
|
while (true) {
|
||||||
long timeRemaining = expiration - _context.clock().now();
|
long timeRemaining = expiration - _context.clock().now();
|
||||||
|
@ -19,12 +19,14 @@ class PacketQueue {
|
|||||||
private I2PAppContext _context;
|
private I2PAppContext _context;
|
||||||
private Log _log;
|
private Log _log;
|
||||||
private I2PSession _session;
|
private I2PSession _session;
|
||||||
|
private ConnectionManager _connectionManager;
|
||||||
private byte _buf[];
|
private byte _buf[];
|
||||||
private ByteCache _cache = ByteCache.getInstance(64, 36*1024);
|
private ByteCache _cache = ByteCache.getInstance(64, 36*1024);
|
||||||
|
|
||||||
public PacketQueue(I2PAppContext context, I2PSession session) {
|
public PacketQueue(I2PAppContext context, I2PSession session, ConnectionManager mgr) {
|
||||||
_context = context;
|
_context = context;
|
||||||
_session = session;
|
_session = session;
|
||||||
|
_connectionManager = mgr;
|
||||||
_buf = _cache.acquire().getData(); // new byte[36*1024];
|
_buf = _cache.acquire().getData(); // new byte[36*1024];
|
||||||
_log = context.logManager().getLog(PacketQueue.class);
|
_log = context.logManager().getLog(PacketQueue.class);
|
||||||
}
|
}
|
||||||
@ -95,7 +97,7 @@ class PacketQueue {
|
|||||||
+ " con: " + conStr;
|
+ " con: " + conStr;
|
||||||
_log.debug(msg);
|
_log.debug(msg);
|
||||||
}
|
}
|
||||||
PacketHandler.displayPacket(packet, "SEND");
|
_connectionManager.getPacketHandler().displayPacket(packet, "SEND");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user