Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit c981833

Browse files
wujincheng2333吴锦程normanmaurer
authored
Remove Channel from map on timeout(#359)
Motivation: When a Channel was closed due a timeout we did miss to remove it from the internal map. Modifications: Remove channel on timeout Result: No more leak in the map Co-authored-by: 吴锦程 <wujincheng@wujinchengdeMacBook-Pro.local> Co-authored-by: Norman Maurer <norman_maurer@apple.com>
1 parent 91c8004 commit c981833

3 files changed

Lines changed: 34 additions & 3 deletions

File tree

codec-classes-quic/src/main/java/io/netty/incubator/codec/quic/QuicheQuicChannel.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import java.util.concurrent.ScheduledFuture;
6161
import java.util.concurrent.TimeUnit;
6262
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
63+
import java.util.function.Consumer;
6364
import java.util.function.Function;
6465

6566
/**
@@ -112,7 +113,7 @@ public void operationComplete(ChannelFuture future) {
112113
private final ChannelHandler streamHandler;
113114
private final Map.Entry<ChannelOption<?>, Object>[] streamOptionsArray;
114115
private final Map.Entry<AttributeKey<?>, Object>[] streamAttrsArray;
115-
private final TimeoutHandler timeoutHandler = new TimeoutHandler();
116+
private final TimeoutHandler timeoutHandler;
116117

117118
private boolean inFireChannelReadCompleteQueue;
118119
private boolean fireChannelReadCompletePending;
@@ -156,6 +157,14 @@ private QuicheQuicChannel(Channel parent, boolean server, ByteBuffer key,
156157
InetSocketAddress remote, boolean supportsDatagram, ChannelHandler streamHandler,
157158
Map.Entry<ChannelOption<?>, Object>[] streamOptionsArray,
158159
Map.Entry<AttributeKey<?>, Object>[] streamAttrsArray) {
160+
this(parent, server, key, remote, supportsDatagram, streamHandler, streamOptionsArray, streamAttrsArray, null);
161+
}
162+
163+
private QuicheQuicChannel(Channel parent, boolean server, ByteBuffer key,
164+
InetSocketAddress remote, boolean supportsDatagram, ChannelHandler streamHandler,
165+
Map.Entry<ChannelOption<?>, Object>[] streamOptionsArray,
166+
Map.Entry<AttributeKey<?>, Object>[] streamAttrsArray,
167+
Consumer<QuicheQuicChannel> timeoutTask) {
159168
super(parent);
160169
config = new QuicheQuicChannelConfig(this);
161170
this.server = server;
@@ -169,6 +178,7 @@ private QuicheQuicChannel(Channel parent, boolean server, ByteBuffer key,
169178
this.streamHandler = streamHandler;
170179
this.streamOptionsArray = streamOptionsArray;
171180
this.streamAttrsArray = streamAttrsArray;
181+
timeoutHandler = new TimeoutHandler(timeoutTask);
172182
}
173183

174184
static QuicheQuicChannel forClient(Channel parent, InetSocketAddress remote, ChannelHandler streamHandler,
@@ -186,6 +196,15 @@ static QuicheQuicChannel forServer(Channel parent, ByteBuffer key, InetSocketAdd
186196
streamHandler, streamOptionsArray, streamAttrsArray);
187197
}
188198

199+
static QuicheQuicChannel forServer(Channel parent, ByteBuffer key, InetSocketAddress remote,
200+
boolean supportsDatagram, ChannelHandler streamHandler,
201+
Map.Entry<ChannelOption<?>, Object>[] streamOptionsArray,
202+
Map.Entry<AttributeKey<?>, Object>[] streamAttrsArray,
203+
Consumer<QuicheQuicChannel> timeoutTask) {
204+
return new QuicheQuicChannel(parent, true, key, remote, supportsDatagram,
205+
streamHandler, streamOptionsArray, streamAttrsArray, timeoutTask);
206+
}
207+
189208
@Override
190209
public boolean isTimedOut() {
191210
return timedOut;
@@ -1469,6 +1488,11 @@ private static final class QuicheQuicChannelAddress extends SocketAddress {
14691488

14701489
private final class TimeoutHandler implements Runnable {
14711490
private ScheduledFuture<?> timeoutFuture;
1491+
private final Consumer<QuicheQuicChannel> timeoutTask;
1492+
1493+
TimeoutHandler(Consumer<QuicheQuicChannel> timeoutTask) {
1494+
this.timeoutTask = timeoutTask;
1495+
}
14721496

14731497
@Override
14741498
public void run() {
@@ -1480,6 +1504,9 @@ public void run() {
14801504

14811505
if (Quiche.quiche_conn_is_closed(connAddr)) {
14821506
forceClose();
1507+
if (timeoutTask != null){
1508+
timeoutTask.accept(QuicheQuicChannel.this);
1509+
}
14831510
} else {
14841511
// We need to call connectionSend when a timeout was triggered.
14851512
// See https://docs.rs/quiche/0.6.0/quiche/struct.Connection.html#method.send.

codec-classes-quic/src/main/java/io/netty/incubator/codec/quic/QuicheQuicCodec.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ protected void putChannel(QuicheQuicChannel channel) {
7171
connections.put(channel.key(), channel);
7272
}
7373

74+
protected void removeChannel(QuicheQuicChannel channel) {
75+
connections.remove(channel.key());
76+
}
77+
7478
@Override
7579
public void handlerAdded(ChannelHandlerContext ctx) {
7680
sockaddrMemory = allocateNativeOrder(Quiche.SIZEOF_SOCKADDR_STORAGE);

codec-classes-quic/src/main/java/io/netty/incubator/codec/quic/QuicheQuicServerCodec.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,10 @@ private QuicheQuicChannel handleServer(ChannelHandlerContext ctx, InetSocketAddr
197197
dcid.getBytes(dcid.readerIndex(), bytes);
198198
key = ByteBuffer.wrap(bytes);
199199
}
200-
201200
QuicheQuicChannel channel = QuicheQuicChannel.forServer(
202201
ctx.channel(), key, sender, config.isDatagramSupported(),
203-
streamHandler, streamOptionsArray, streamAttrsArray);
202+
streamHandler, streamOptionsArray, streamAttrsArray, this::removeChannel);
203+
204204
Quic.setupChannel(channel, optionsArray, attrsArray, handler, LOGGER);
205205
QuicSslEngine engine = sslEngineProvider.apply(channel);
206206
if (!(engine instanceof QuicheQuicSslEngine)) {

0 commit comments

Comments
 (0)