Added close hints when the connection is shutdown

This commit is contained in:
nathan 2018-04-04 14:58:24 +02:00
parent 73a5af7a95
commit 615e224292
5 changed files with 43 additions and 18 deletions

View File

@ -690,6 +690,11 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements CryptoConne
closeLatch.countDown(); closeLatch.countDown();
} }
final void
forceClose() {
this.channelWrapper.close(this, this.sessionManager, true);
}
/** /**
* Closes the connection, but does not remove any listeners * Closes the connection, but does not remove any listeners
*/ */
@ -757,7 +762,7 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements CryptoConne
synchronized (this.channelIsClosed) { synchronized (this.channelIsClosed) {
if (!this.channelIsClosed.get()) { if (!this.channelIsClosed.get()) {
// this will have netty call "channelInactive()" // this will have netty call "channelInactive()"
this.channelWrapper.close(this, this.sessionManager); this.channelWrapper.close(this, this.sessionManager, false);
// want to wait for the "channelInactive()" method to FINISH ALL TYPES before allowing our current thread to continue! // want to wait for the "channelInactive()" method to FINISH ALL TYPES before allowing our current thread to continue!
try { try {

View File

@ -122,7 +122,7 @@ class ChannelLocalWrapper implements ChannelWrapper, ConnectionPoint {
@Override @Override
public public
void close(ConnectionImpl connection, ISessionManager sessionManager) { void close(ConnectionImpl connection, ISessionManager sessionManager, boolean hintedClose) {
long maxShutdownWaitTimeInMilliSeconds = EndPoint.maxShutdownWaitTimeInMilliSeconds; long maxShutdownWaitTimeInMilliSeconds = EndPoint.maxShutdownWaitTimeInMilliSeconds;
this.shouldFlush.set(false); this.shouldFlush.set(false);

View File

@ -15,6 +15,7 @@
*/ */
package dorkbox.network.connection.wrapper; package dorkbox.network.connection.wrapper;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import dorkbox.network.connection.ConnectionPoint; import dorkbox.network.connection.ConnectionPoint;
@ -69,12 +70,26 @@ class ChannelNetwork implements ConnectionPoint {
return channel.eventLoop().newPromise(); return channel.eventLoop().newPromise();
} }
public void close(final int delay, final long maxShutdownWaitTimeInMilliSeconds) {
void close(long maxShutdownWaitTimeInMilliSeconds) {
shouldFlush.set(false); shouldFlush.set(false);
if (channel.isActive()) { if (channel.isActive()) {
channel.close() if (delay > 0) {
.awaitUninterruptibly(maxShutdownWaitTimeInMilliSeconds); // for UDP, we send a hint to the other connection that we should close. While not always 100% successful, this helps
// clean up connections on the remote end. So we want to wait a short amount of time for this to be successful
channel.eventLoop()
.schedule(new Runnable() {
@Override
public
void run() {
channel.close()
.awaitUninterruptibly(maxShutdownWaitTimeInMilliSeconds);
}
}, delay, TimeUnit.MILLISECONDS);
}
else {
channel.close()
.awaitUninterruptibly(maxShutdownWaitTimeInMilliSeconds);
}
} }
} }
} }

View File

@ -154,24 +154,29 @@ class ChannelNetworkWrapper implements ChannelWrapper {
@Override @Override
public public
void close(final ConnectionImpl connection, final ISessionManager sessionManager) { void close(final ConnectionImpl connection, final ISessionManager sessionManager, boolean hintedClose) {
long maxShutdownWaitTimeInMilliSeconds = EndPoint.maxShutdownWaitTimeInMilliSeconds; long maxShutdownWaitTimeInMilliSeconds = EndPoint.maxShutdownWaitTimeInMilliSeconds;
if (this.tcp != null) { if (this.tcp != null) {
this.tcp.close(maxShutdownWaitTimeInMilliSeconds); this.tcp.close(0, maxShutdownWaitTimeInMilliSeconds);
} }
if (this.udp != null) { if (this.udp != null) {
// send a hint to the other connection that we should close. While not always 100% successful, this helps clean up connections if (hintedClose) {
// on the remote end // we already hinted that we should close this channel... don't do it again!
try { this.udp.close(0, maxShutdownWaitTimeInMilliSeconds);
this.udp.write(new DatagramCloseMessage()); }
this.udp.flush(); else {
Thread.yield(); // send a hint to the other connection that we should close. While not always 100% successful, this helps clean up connections
} catch (Exception e) { // on the remote end
e.printStackTrace(); try {
this.udp.write(new DatagramCloseMessage());
this.udp.flush();
} catch (Exception e) {
e.printStackTrace();
}
this.udp.close(200, maxShutdownWaitTimeInMilliSeconds);
} }
this.udp.close(maxShutdownWaitTimeInMilliSeconds);
} }
// we need to yield the thread here, so that the socket has a chance to close // we need to yield the thread here, so that the socket has a chance to close

View File

@ -53,7 +53,7 @@ interface ChannelWrapper {
*/ */
String getRemoteHost(); String getRemoteHost();
void close(ConnectionImpl connection, ISessionManager sessionManager); void close(ConnectionImpl connection, ISessionManager sessionManager, boolean hintedClose);
int id(); int id();