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();
}
final void
forceClose() {
this.channelWrapper.close(this, this.sessionManager, true);
}
/**
* Closes the connection, but does not remove any listeners
*/
@ -757,7 +762,7 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements CryptoConne
synchronized (this.channelIsClosed) {
if (!this.channelIsClosed.get()) {
// 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!
try {

View File

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

View File

@ -15,6 +15,7 @@
*/
package dorkbox.network.connection.wrapper;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import dorkbox.network.connection.ConnectionPoint;
@ -69,12 +70,26 @@ class ChannelNetwork implements ConnectionPoint {
return channel.eventLoop().newPromise();
}
public
void close(long maxShutdownWaitTimeInMilliSeconds) {
void close(final int delay, final long maxShutdownWaitTimeInMilliSeconds) {
shouldFlush.set(false);
if (channel.isActive()) {
channel.close()
.awaitUninterruptibly(maxShutdownWaitTimeInMilliSeconds);
if (delay > 0) {
// 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
public
void close(final ConnectionImpl connection, final ISessionManager sessionManager) {
void close(final ConnectionImpl connection, final ISessionManager sessionManager, boolean hintedClose) {
long maxShutdownWaitTimeInMilliSeconds = EndPoint.maxShutdownWaitTimeInMilliSeconds;
if (this.tcp != null) {
this.tcp.close(maxShutdownWaitTimeInMilliSeconds);
this.tcp.close(0, maxShutdownWaitTimeInMilliSeconds);
}
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
// on the remote end
try {
this.udp.write(new DatagramCloseMessage());
this.udp.flush();
Thread.yield();
} catch (Exception e) {
e.printStackTrace();
if (hintedClose) {
// we already hinted that we should close this channel... don't do it again!
this.udp.close(0, maxShutdownWaitTimeInMilliSeconds);
}
else {
// 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
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

View File

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