Skip to content

Commit db31177

Browse files
committed
Correctly handle pending reads during a start tls upgrade.
Motivation: NetSocket implementation does pause the socket on a TLS upgrade but relies on the VertxConnection pause that still cumulates buffers in its pending queue. Since obtaining an SSL context is asynchronous, there can be a client hello sent by the client that will be read and sit in the VertxConnection pending list and will be missed by the SSL handler. Changes: During a TLS upgrade we want buffers to actually remains in the channel so we should pause channel reading instead of pausing the VertxConnection to ensure the pipeline won't see any read during the SSL context resolution.
1 parent 16cf5a7 commit db31177

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

vertx-core/src/main/java/io/vertx/core/net/impl/tcp/NetSocketImpl.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private Future<Void> sslUpgrade(String serverName, SSLOptions sslOptions, ByteBu
127127
applicationProtocols = null;
128128
}
129129
if (chctx.pipeline().get("ssl") == null) {
130-
doPause();
130+
chctx.channel().config().setAutoRead(false);
131131
Future<SslChannelProvider> f;
132132
if (sslOptions instanceof ClientSSLOptions) {
133133
ClientSSLOptions clientSSLOptions = (ClientSSLOptions) sslOptions;
@@ -145,6 +145,7 @@ private Future<Void> sslUpgrade(String serverName, SSLOptions sslOptions, ByteBu
145145
ChannelPromise promise = chctx.newPromise();
146146
writeToChannel(msg, true, promise);
147147
promise.addListener(res -> {
148+
chctx.channel().config().setAutoRead(true);
148149
if (res.isSuccess()) {
149150
ChannelPromise channelPromise = chctx.newPromise();
150151
chctx.pipeline().addFirst("handshaker", new SslHandshakeCompletionHandler(channelPromise));
@@ -159,13 +160,16 @@ private Future<Void> sslUpgrade(String serverName, SSLOptions sslOptions, ByteBu
159160
}
160161
chctx.pipeline().addFirst("ssl", sslHandler);
161162
channelPromise.addListener(p);
163+
doPause();
162164
} else {
163165
p.fail(res.cause());
164166
}
165167
});
166168
return p.future();
167169
}).transform(ar -> {
168-
doResume();
170+
if (ar.succeeded()) {
171+
doResume();
172+
}
169173
return (Future<Void>) ar;
170174
});
171175
} else {

vertx-core/src/test/java/io/vertx/tests/net/NetTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,6 +2089,31 @@ public void start(Promise<Void> startPromise) {
20892089
}
20902090
}
20912091

2092+
@Test
2093+
public void testDirectTlsUpgrade(Checkpoint checkpoint) throws Exception {
2094+
server.connectHandler(socket -> {
2095+
socket.upgradeToSsl(new ServerSSLOptions().setKeyCertOptions(Cert.SERVER_JKS.get()))
2096+
.onComplete(TestUtils.onSuccess(v1 -> {
2097+
socket.handler(socket::write);
2098+
socket.endHandler(v2 -> socket.end());
2099+
}));
2100+
});
2101+
server.listen(1234, "localhost").await();
2102+
NetSocket socket = client.connect(new ConnectOptions()
2103+
.setPort(1234)
2104+
.setHost("localhost")
2105+
.setSsl(true)
2106+
.setSslOptions(new ClientSSLOptions()
2107+
.setHostnameVerificationAlgorithm("")
2108+
.setTrustAll(true))).await();
2109+
socket.handler(chunk -> {
2110+
assertEquals("test", chunk.toString());
2111+
socket.end();
2112+
});
2113+
socket.endHandler(v -> checkpoint.succeed());
2114+
socket.write("test").await();
2115+
}
2116+
20922117
public static class NativeVertxProvider implements VertxProvider {
20932118
@Override
20942119
public Vertx call() throws Exception {

0 commit comments

Comments
 (0)