Skip to content

Commit e13bd94

Browse files
committed
QuicEndpoint should unbind on context close hook.
1 parent c0d13f7 commit e13bd94

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

vertx-core/src/main/java/io/vertx/core/net/impl/quic/QuicEndpointImpl.java

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
import io.netty.bootstrap.Bootstrap;
1414
import io.netty.channel.Channel;
1515
import io.netty.channel.ChannelFuture;
16+
import io.netty.channel.ChannelFutureListener;
1617
import io.netty.channel.ChannelHandler;
1718
import io.netty.handler.codec.quic.BoringSSLKeylog;
1819
import io.netty.handler.codec.quic.FlushStrategy;
1920
import io.netty.handler.codec.quic.QuicCodecBuilder;
2021
import io.netty.util.internal.PlatformDependent;
22+
import io.vertx.core.Closeable;
2123
import io.vertx.core.Completable;
2224
import io.vertx.core.Future;
2325
import io.vertx.core.internal.ContextInternal;
@@ -40,12 +42,13 @@
4042
import java.net.InetSocketAddress;
4143
import java.time.Duration;
4244
import java.util.EnumMap;
45+
import java.util.Objects;
4346
import java.util.concurrent.TimeUnit;
4447

4548
/**
4649
* @author <a href="mailto:[email protected]">Julien Viet</a>
4750
*/
48-
public abstract class QuicEndpointImpl implements QuicEndpointInternal, MetricsProvider {
51+
public abstract class QuicEndpointImpl implements QuicEndpointInternal, MetricsProvider, Closeable {
4952

5053
private static final EnumMap<QuicCongestionControlAlgorithm, io.netty.handler.codec.quic.QuicCongestionControlAlgorithm> CC_MAP = new EnumMap<>(QuicCongestionControlAlgorithm.class);
5154

@@ -62,6 +65,7 @@ public abstract class QuicEndpointImpl implements QuicEndpointInternal, MetricsP
6265
private Channel channel;
6366
protected ConnectionGroup connectionGroup;
6467
private FlushStrategy flushStrategy;
68+
private ContextInternal context;
6569

6670
public QuicEndpointImpl(VertxInternal vertx, QuicEndpointOptions options) {
6771

@@ -95,7 +99,7 @@ public QuicEndpointImpl(VertxInternal vertx, QuicEndpointOptions options) {
9599
}
96100

97101
this.options = options;
98-
this.vertx = vertx;
102+
this.vertx = Objects.requireNonNull(vertx);
99103
this.manager = new SslContextManager(new SSLEngineOptions() {
100104
@Override
101105
public SSLEngineOptions copy() {
@@ -183,15 +187,28 @@ protected void handleBind(Channel channel, QuicEndpointMetrics<?, ?> metrics) {
183187
protected void handleClose(Completable<Void> completion) {
184188
PromiseInternal<Void> promise = (PromiseInternal<Void>) completion;
185189
Channel ch = channel;
186-
ch.close().addListener(promise);
190+
ch.close().addListener((ChannelFutureListener) future -> {
191+
ContextInternal ctx;
192+
synchronized (QuicEndpointImpl.this) {
193+
ctx = context;
194+
context = null;
195+
}
196+
ctx.removeCloseHook(QuicEndpointImpl.this);
197+
}).addListener(promise);
187198
}
188199
};
189200
}
190201

191202
@Override
192203
public Future<Integer> bind(SocketAddress address) {
193-
ContextInternal context = vertx.getOrCreateContext();
194-
Future<SslContextProvider> f1 = manager.resolveSslContextProvider(options.getSslOptions(), context);
204+
ContextInternal current = vertx.getOrCreateContext();
205+
synchronized (this) {
206+
if (context != null) {
207+
return current.failedFuture("Already bound");
208+
}
209+
context = current;
210+
}
211+
Future<SslContextProvider> f1 = manager.resolveSslContextProvider(options.getSslOptions(), current);
195212
return f1.compose(sslContextProvider -> {
196213
VertxMetrics metricsFactory = vertx.metrics();
197214
QuicEndpointMetrics<?, ?> metrics;
@@ -200,9 +217,10 @@ public Future<Integer> bind(SocketAddress address) {
200217
} else {
201218
metrics = null;
202219
}
203-
return bind(context, address, metrics)
220+
return bind(current, address, metrics)
204221
.map(ch -> {
205222
handleBind(ch, metrics);
223+
context.addCloseHook(this);
206224
return ((InetSocketAddress)ch.localAddress()).getPort();
207225
});
208226
});
@@ -228,4 +246,9 @@ public QuicEndpointInternal flushStrategy(FlushStrategy flushStrategy) {
228246
this.flushStrategy = flushStrategy;
229247
return this;
230248
}
249+
250+
@Override
251+
public void close(Completable<Void> completion) {
252+
close().onComplete(completion);
253+
}
231254
}

vertx-core/src/test/java/io/vertx/tests/net/quic/QuicServerTest.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@
1616
import io.netty.channel.socket.ChannelOutputShutdownException;
1717
import io.netty.handler.codec.quic.QuicClosedChannelException;
1818
import io.netty.util.NetUtil;
19-
import io.vertx.core.Context;
20-
import io.vertx.core.Future;
21-
import io.vertx.core.Promise;
22-
import io.vertx.core.Vertx;
19+
import io.vertx.core.*;
2320
import io.vertx.core.buffer.Buffer;
21+
import io.vertx.core.internal.ContextInternal;
2422
import io.vertx.core.internal.quic.QuicConnectionInternal;
2523
import io.vertx.core.net.*;
2624
import io.vertx.test.core.LinuxOrOsx;
@@ -873,6 +871,22 @@ private void testWriteWhenClosed(boolean write) throws Exception {
873871
}
874872
}
875873

874+
@Test
875+
public void testRebind() {
876+
Deployable deployable = ctx -> {
877+
QuicServer server = QuicServer.create(vertx, serverOptions());
878+
server.handler(connection -> {
879+
880+
});
881+
return server.bind(SocketAddress.inetSocketAddress(9999, "localhost"));
882+
};
883+
int num = 4;
884+
for (int i = 0;i < num;i++) {
885+
String id = vertx.deployVerticle(deployable).await();
886+
vertx.undeploy(id).await();
887+
}
888+
}
889+
876890
/* @Test
877891
public void testSoReuse() throws Exception {
878892

0 commit comments

Comments
 (0)