Skip to content

Commit b4d35ce

Browse files
authored
Merge branch 'eclipse-vertx:master' into cidr-change
2 parents bea0492 + acb02de commit b4d35ce

File tree

19 files changed

+423
-79
lines changed

19 files changed

+423
-79
lines changed

pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,24 @@
9494
<classifier>linux-x86_64</classifier>
9595
<scope>test</scope>
9696
</dependency>
97+
<dependency>
98+
<groupId>io.netty</groupId>
99+
<artifactId>netty-transport-native-epoll</artifactId>
100+
<classifier>linux-aarch_64</classifier>
101+
<scope>test</scope>
102+
</dependency>
97103
<dependency>
98104
<groupId>io.netty</groupId>
99105
<artifactId>netty-transport-native-kqueue</artifactId>
100106
<classifier>osx-x86_64</classifier>
101107
<scope>test</scope>
102108
</dependency>
109+
<dependency>
110+
<groupId>io.netty</groupId>
111+
<artifactId>netty-transport-native-kqueue</artifactId>
112+
<classifier>osx-aarch_64</classifier>
113+
<scope>test</scope>
114+
</dependency>
103115
</dependencies>
104116

105117
<profiles>

vertx-mssql-client/src/main/java/io/vertx/mssqlclient/impl/MSSQLSocketConnection.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
import io.vertx.core.impl.future.PromiseInternal;
2222
import io.vertx.core.net.ClientSSLOptions;
2323
import io.vertx.core.net.HostAndPort;
24-
import io.vertx.core.net.impl.NetSocketInternal;
25-
import io.vertx.core.net.impl.SSLHelper;
26-
import io.vertx.core.net.impl.SslChannelProvider;
27-
import io.vertx.core.net.impl.SslHandshakeCompletionHandler;
24+
import io.vertx.core.net.impl.*;
2825
import io.vertx.core.spi.metrics.ClientMetrics;
2926
import io.vertx.mssqlclient.MSSQLConnectOptions;
3027
import io.vertx.mssqlclient.MSSQLInfo;
@@ -116,7 +113,7 @@ Future<Void> enableSsl(boolean clientConfigSsl, byte encryptionLevel, MSSQLConne
116113
// options.getApplicationLayerProtocols()
117114
Future<SslChannelProvider> f = sslHelper.resolveSslChannelProvider(sslOptions, "", false, null, null, context);
118115
return f.compose(provider -> {
119-
SslHandler sslHandler = provider.createClientSslHandler(socket.remoteAddress(), null, sslOptions.isUseAlpn(), sslOptions.isTrustAll(), sslOptions.getSslHandshakeTimeout(), sslOptions.getSslHandshakeTimeoutUnit());
116+
SslHandler sslHandler = provider.createClientSslHandler(socket.remoteAddress(), null, sslOptions.isUseAlpn(), sslOptions.getSslHandshakeTimeout(), sslOptions.getSslHandshakeTimeoutUnit());
120117

121118
// 3. TdsSslHandshakeCodec manages SSL payload encapsulated in TDS packets
122119
TdsSslHandshakeCodec tdsSslHandshakeCodec = new TdsSslHandshakeCodec();

vertx-mysql-client/src/main/java/io/vertx/mysqlclient/impl/MySQLSocketConnection.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.vertx.mysqlclient.MySQLAuthenticationPlugin;
3131
import io.vertx.mysqlclient.MySQLConnectOptions;
3232
import io.vertx.mysqlclient.SslMode;
33+
import io.vertx.mysqlclient.impl.codec.ClearCachedStatementsEvent;
3334
import io.vertx.mysqlclient.impl.codec.MySQLCodec;
3435
import io.vertx.mysqlclient.impl.codec.MySQLPacketDecoder;
3536
import io.vertx.mysqlclient.impl.command.InitialHandshakeCommand;
@@ -114,6 +115,21 @@ protected <R> void doSchedule(CommandBase<R> cmd, Handler<AsyncResult<R>> handle
114115
}
115116
}
116117

118+
@Override
119+
protected void handleMessage(Object msg) {
120+
if (msg == ClearCachedStatementsEvent.INSTANCE) {
121+
clearCachedStatements();
122+
} else {
123+
super.handleMessage(msg);
124+
}
125+
}
126+
127+
private void clearCachedStatements() {
128+
if (this.psCache != null) {
129+
this.psCache.clear();
130+
}
131+
}
132+
117133
public Future<Void> upgradeToSsl(ClientSSLOptions sslOptions) {
118134
return socket.upgradeToSsl(sslOptions);
119135
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.vertx.mysqlclient.impl.codec;
2+
3+
/**
4+
* An event that signals all cached statements must be cleared from the cache.
5+
*/
6+
public class ClearCachedStatementsEvent {
7+
8+
public static final ClearCachedStatementsEvent INSTANCE = new ClearCachedStatementsEvent();
9+
10+
private ClearCachedStatementsEvent() {
11+
// Singleton
12+
}
13+
}

vertx-mysql-client/src/main/java/io/vertx/mysqlclient/impl/codec/ResetConnectionCommandCodec.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ void encode(MySQLEncoder encoder) {
3030

3131
@Override
3232
void decodePayload(ByteBuf payload, int payloadLength) {
33+
encoder.chctx.fireChannelRead(ClearCachedStatementsEvent.INSTANCE);
3334
handleOkPacketOrErrorPacketPayload(payload);
3435
}
3536

vertx-mysql-client/src/test/java/io/vertx/mysqlclient/MySQLTLSTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
import io.vertx.core.Future;
1515
import io.vertx.core.Vertx;
16+
import io.vertx.core.VertxOptions;
17+
import io.vertx.core.buffer.Buffer;
18+
import io.vertx.core.dns.AddressResolverOptions;
1619
import io.vertx.core.net.ClientSSLOptions;
1720
import io.vertx.core.net.PemKeyCertOptions;
1821
import io.vertx.core.net.PemTrustOptions;
@@ -295,6 +298,49 @@ public void testConnFailWithVerifyIdentitySslMode(TestContext ctx) {
295298
}));
296299
}
297300

301+
@Test
302+
public void testVerifyIdentityInvalidHostname(TestContext ctx) {
303+
options.setSslMode(SslMode.VERIFY_IDENTITY);
304+
options.getSslOptions()
305+
.setHostnameVerificationAlgorithm("HTTPS")
306+
.setTrustOptions(new PemTrustOptions().addCertPath("tls/files/ca.pem"))
307+
.setKeyCertOptions(new PemKeyCertOptions()
308+
.setCertPath("tls/files/client-cert.pem")
309+
.setKeyPath("tls/files/client-key.pem"));
310+
// The hostname in the test certificate is mysql.vertx.test, so 'localhost' should make for a failed connection
311+
options.setHost("localhost");
312+
313+
MySQLConnection.connect(vertx, options).onComplete( ctx.asyncAssertFailure(err -> {
314+
ctx.assertEquals(err.getMessage(), "No name matching localhost found");
315+
}));
316+
}
317+
318+
@Test
319+
public void testVerifyIdentityCorrectHostname(TestContext ctx) {
320+
Vertx vertxWithHosts = Vertx.vertx(
321+
new VertxOptions()
322+
.setAddressResolverOptions(
323+
new AddressResolverOptions()
324+
.setHostsValue(Buffer.buffer("127.0.0.1 mysql.vertx.test\n"))
325+
)
326+
);
327+
328+
options.setSslMode(SslMode.VERIFY_IDENTITY);
329+
options.getSslOptions()
330+
.setHostnameVerificationAlgorithm("HTTPS")
331+
.setTrustOptions(new PemTrustOptions().addCertPath("tls/files/ca.pem"))
332+
.setKeyCertOptions(new PemKeyCertOptions()
333+
.setCertPath("tls/files/client-cert.pem")
334+
.setKeyPath("tls/files/client-key.pem"));
335+
// The hostname in the test certificate is mysql.vertx.test
336+
options.setHost("mysql.vertx.test");
337+
338+
MySQLConnection.connect(vertxWithHosts, options).onComplete( ctx.asyncAssertSuccess(conn -> {
339+
ctx.assertTrue(conn.isSSL());
340+
vertxWithHosts.close();
341+
}));
342+
}
343+
298344
@Test
299345
public void testConnFail(TestContext ctx) {
300346
options.setSslMode(SslMode.REQUIRED);

vertx-mysql-client/src/test/java/io/vertx/mysqlclient/MySQLUtilityCommandTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.vertx.ext.unit.junit.VertxUnitRunner;
1818
import io.vertx.sqlclient.Row;
1919
import io.vertx.sqlclient.RowSet;
20+
import io.vertx.sqlclient.Tuple;
2021
import org.junit.After;
2122
import org.junit.Assume;
2223
import org.junit.Before;
@@ -160,6 +161,19 @@ public void testResetConnection(TestContext ctx) {
160161
}));
161162
}
162163

164+
@Test
165+
public void testResetConnectionClearsPreparedStatementCache(TestContext ctx) {
166+
Assume.assumeFalse(rule.isUsingMySQL5_6());
167+
MySQLConnectOptions connectOptions = new MySQLConnectOptions(options).setCachePreparedStatements(true);
168+
MySQLConnection.connect(vertx, connectOptions).onComplete(ctx.asyncAssertSuccess(conn -> {
169+
conn.preparedQuery("SELECT 1").execute(Tuple.tuple()).onComplete(ctx.asyncAssertSuccess(res1 -> {
170+
conn.resetConnection().onComplete(ctx.asyncAssertSuccess(rst -> {
171+
conn.preparedQuery("SELECT 1").execute(Tuple.tuple()).onComplete(ctx.asyncAssertSuccess());
172+
}));
173+
}));
174+
}));
175+
}
176+
163177
@Test
164178
public void testChangeUser(TestContext ctx) {
165179
MySQLConnection.connect(vertx, options).onComplete( ctx.asyncAssertSuccess(conn -> {
Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
-----BEGIN CERTIFICATE-----
2-
MIIDBDCCAeygAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR
3-
TF9TZXJ2ZXJfOC4wLjE3X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X
4-
DTE5MDkwMjAzMjc1MVoXDTI5MDgzMDAzMjc1MVowQDE+MDwGA1UEAww1TXlTUUxf
5-
U2VydmVyXzguMC4xN19BdXRvX0dlbmVyYXRlZF9TZXJ2ZXJfQ2VydGlmaWNhdGUw
6-
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDg00pPuJv078OExAy7wfx/
7-
YsPiukl+OpyQAuF/45La5yDIwx3v55MxYqkX9TCuAIZUprWVllf51sOkNHsB/skC
8-
ZCYiXFlPmi9nCiK4TAuqN5c0rdjVdn8eFt4/CeAzHDC2bvoKbnOwDLKtponqbW8u
9-
nYkXWQDAxYyojxIUc3wNuyPkefFTkEjuIl3DyhyKZhfFPg0mbDB8t91gSB6oBrEa
10-
K9LMHJ4fWDsOSRLru8wUXPdstMD8zqKQjVfvG/4U5gb+dYycaZ+cRmPgHjarI+St
11-
R2ZG9wXs/J1wllciz4fr0je7+R2j7HHKqTY6JqSz0hZjd1Hej2zWAho1K5KqkDbt
12-
AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAAb0+bViRmYt
13-
Enm/jDGyGFCUGCbh8xnxREBLe3SZZTaJ8mVJOZ9wsC7NBCEqkgt6FzcSxIftF0Iz
14-
ppYpL0XqyYRMHnrtWZBzgkflhTltdNhVTl4sdfrYxJ7kAJ//WSk/wGsa6U7jD5SW
15-
I3rWfGOcVbnRA+rBDxslg7hSbnoIH19FUBqiIsAMQgSm1/6zlOsA7VPFvSVojSI8
16-
oGbOOmFsX/Jm793TJvT5ly8ZOCF/EMD+QnK/pS8BiDbTYauvU5Rzfl4fEQVW55YL
17-
YQAdSj/sUYAcv47Qlx7hp1GrLWHgVynTIC+kwEWKczNQofhL6Ewh3QutiwwD39+K
18-
KmqT2KQLyKA=
2+
MIIDZDCCAkygAwIBAgIUfAA0jelPI0Xwr+tkPO8Oz7OnNZkwDQYJKoZIhvcNAQEN
3+
BQAwPDE6MDgGA1UEAwwxTXlTUUxfU2VydmVyXzguMC4xN19BdXRvX0dlbmVyYXRl
4+
ZF9DQV9DZXJ0aWZpY2F0ZTAeFw0yNDAzMTExNTE2MDVaFw00NDAzMDYxNTE2MDVa
5+
MBsxGTAXBgNVBAMMEG15c3FsLnZlcnR4LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUA
6+
A4IBDwAwggEKAoIBAQDg00pPuJv078OExAy7wfx/YsPiukl+OpyQAuF/45La5yDI
7+
wx3v55MxYqkX9TCuAIZUprWVllf51sOkNHsB/skCZCYiXFlPmi9nCiK4TAuqN5c0
8+
rdjVdn8eFt4/CeAzHDC2bvoKbnOwDLKtponqbW8unYkXWQDAxYyojxIUc3wNuyPk
9+
efFTkEjuIl3DyhyKZhfFPg0mbDB8t91gSB6oBrEaK9LMHJ4fWDsOSRLru8wUXPds
10+
tMD8zqKQjVfvG/4U5gb+dYycaZ+cRmPgHjarI+StR2ZG9wXs/J1wllciz4fr0je7
11+
+R2j7HHKqTY6JqSz0hZjd1Hej2zWAho1K5KqkDbtAgMBAAGjfzB9MAwGA1UdEwEB
12+
/wQCMAAwHQYDVR0OBBYEFIiHxyASKXMPzKI/uDEi36Afv6ExME4GA1UdIwRHMEWh
13+
QKQ+MDwxOjA4BgNVBAMMMU15U1FMX1NlcnZlcl84LjAuMTdfQXV0b19HZW5lcmF0
14+
ZWRfQ0FfQ2VydGlmaWNhdGWCAQEwDQYJKoZIhvcNAQENBQADggEBAAPIZqs8818j
15+
7+J6W7WDYlmVRyDK1BH/16/tAAUGSo7IJt09bSp6bm2eAlEp9nDgLLTQSPjfGz+f
16+
Zp1OIdeeKouOFeZfZ5924n7RS1eP49PGD2ZTpk551Rnthni7isL8fOwBx+kZzUIM
17+
7AQaEi8By5wpwcfNowSMlKR/Wm9OTGqZmmHSixK3HrI6yvHDJwe7fZ6dAl9DDViX
18+
j0hAQnuROsWz3aZkTF3DJ+CGlYjdQvArrazNgsrBbRvAH7VoGYICxahEYMRenXxz
19+
1Y1ITH7Mi/+53HQge/RoMCVSNQuyVgr3i5fgz5P+GFxdFc0HCC9uanD/PcObOhBs
20+
38m1J0pH5Q4=
1921
-----END CERTIFICATE-----

vertx-pg-client/README.adoc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ mvn test -DcontainerFixedPort
311311
You can run tests with an external database:
312312

313313
- the script `src/test/resources/create-postgres.sql` creates the test data
314-
- the `TLSTest` expects the database to be configured with SSL with `src/test/resources/tls/server.key` / `src/test/resources/tls/server.cert``
314+
- the `TLSTest` expects the database to be configured with SSL with `src/test/resources/tls/server.key` / `src/test/resources/tls/server.cert` `src/test/resources/tls/pg_hba.conf` as an example how to force SSL
315315

316316
You need to add some properties for testing:
317317

@@ -321,6 +321,7 @@ You need to add some properties for testing:
321321

322322
- connection.uri(mandatory): configure the client to connect the specified database
323323
- tls.connection.uri(mandatory): configure the client to run `TLSTest` with the specified Postgres with SSL enabled
324+
- tls.force.connection.uri(mandatory): configure the client to run `TLSTest` with the specified Postgres with SSL forced (only option)
324325
- unix.socket.directory(optional): the single unix socket directory(multiple socket directories are not supported) to test Unix domain socket with a specified database, domain socket tests will be skipped if this property is not specified
325326
(Note: Make sure you can access the unix domain socket with this directory under your host machine)
326327
- unix.socket.port(optional): unix socket file is named `.s.PGSQL.nnnn` and `nnnn` is the server's port number,
@@ -339,5 +340,5 @@ Run the Postgres containers with `docker compose`:
339340
Run tests:
340341

341342
```
342-
> mvn test -Dconnection.uri=postgres://$username:$password@$host:$port/$database -Dtls.connection.uri=postgres://$username:$password@$host:$port/$database -Dunix.socket.directory=$path -Dunix.socket.port=$port
343+
> mvn test -Dconnection.uri=postgres://$username:$password@$host:$port/$database -Dtls.connection.uri=postgres://$username:$password@$host:$port/$database -Dtls.force.connection.uri=postgres://$username:$password@$host:$port/$database -Dunix.socket.directory=$path -Dunix.socket.port=$port
343344
```

vertx-pg-client/src/main/java/io/vertx/pgclient/impl/PgConnectionFactory.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -70,56 +70,61 @@ protected Future<Connection> doConnectInternal(PgConnectOptions options, Context
7070
} catch (Exception e) {
7171
return context.failedFuture(e);
7272
}
73-
String username = options.getUser();
74-
String password = options.getPassword();
75-
String database = options.getDatabase();
7673
SocketAddress server = options.getSocketAddress();
77-
Map<String, String> properties = options.getProperties() != null ? Collections.unmodifiableMap(options.getProperties()) : null;
78-
return doConnect(server, context, options).flatMap(conn -> {
79-
PgSocketConnection socket = (PgSocketConnection) conn;
80-
socket.init();
81-
return Future.<Connection>future(p -> socket.sendStartupMessage(username, password, database, properties, p))
82-
.map(conn);
83-
});
74+
return connect(server, context, true, options);
8475
}
8576

86-
public void cancelRequest(PgConnectOptions options, int processId, int secretKey, Handler<AsyncResult<Void>> handler) {
87-
doConnect(options.getSocketAddress(), vertx.createEventLoopContext(), options).onComplete(ar -> {
88-
if (ar.succeeded()) {
89-
PgSocketConnection conn = (PgSocketConnection) ar.result();
90-
conn.sendCancelRequestMessage(processId, secretKey, handler);
91-
} else {
92-
handler.handle(Future.failedFuture(ar.cause()));
93-
}
94-
});
77+
public Future<Void> cancelRequest(PgConnectOptions options, int processId, int secretKey) {
78+
return connect(options.getSocketAddress(), vertx.createEventLoopContext(), false, options)
79+
.compose(conn -> {
80+
PgSocketConnection socket = (PgSocketConnection) conn;
81+
return socket.sendCancelRequestMessage(processId, secretKey);
82+
});
9583
}
9684

97-
private Future<Connection> doConnect(SocketAddress server, ContextInternal context, PgConnectOptions options) {
85+
private Future<Connection> connect(SocketAddress server, ContextInternal context, boolean sendStartupMessage, PgConnectOptions options) {
9886
SslMode sslMode = options.isUsingDomainSocket() ? SslMode.DISABLE : options.getSslMode();
9987
ConnectOptions connectOptions = new ConnectOptions()
10088
.setRemoteAddress(server);
10189
Future<Connection> connFuture;
10290
switch (sslMode) {
10391
case DISABLE:
104-
connFuture = doConnect(connectOptions, context, false, options);
92+
connFuture = connect(connectOptions, context, false, sendStartupMessage, options);
10593
break;
10694
case ALLOW:
107-
connFuture = doConnect(connectOptions, context, false, options).recover(err -> doConnect(connectOptions, context, true, options));
95+
connFuture = connect(connectOptions, context, false, sendStartupMessage, options).recover(err -> connect(connectOptions, context, true, sendStartupMessage, options));
10896
break;
10997
case PREFER:
110-
connFuture = doConnect(connectOptions, context, true, options).recover(err -> doConnect(connectOptions, context, false, options));
98+
connFuture = connect(connectOptions, context, true, sendStartupMessage, options).recover(err -> connect(connectOptions, context, false, sendStartupMessage, options));
11199
break;
112100
case REQUIRE:
113101
case VERIFY_CA:
114102
case VERIFY_FULL:
115-
connFuture = doConnect(connectOptions, context, true, options);
103+
connFuture = connect(connectOptions, context, true, sendStartupMessage, options);
116104
break;
117105
default:
118106
return context.failedFuture(new IllegalArgumentException("Unsupported SSL mode"));
119107
}
120108
return connFuture;
121109
}
122110

111+
private Future<Connection> connect(ConnectOptions connectOptions, ContextInternal context, boolean ssl, boolean sendStartupMessage, PgConnectOptions options) {
112+
Future<Connection> res = doConnect(connectOptions, context, ssl, options);
113+
if (sendStartupMessage) {
114+
return res.flatMap(conn -> {
115+
PgSocketConnection socket = (PgSocketConnection) conn;
116+
socket.init();
117+
String username = options.getUser();
118+
String password = options.getPassword();
119+
String database = options.getDatabase();
120+
Map<String, String> properties = options.getProperties() != null ? Collections.unmodifiableMap(options.getProperties()) : null;
121+
return socket.sendStartupMessage(username, password, database, properties);
122+
});
123+
} else {
124+
return res;
125+
}
126+
}
127+
123128
private Future<Connection> doConnect(ConnectOptions connectOptions, ContextInternal context, boolean ssl, PgConnectOptions options) {
124129
Future<NetSocket> soFut;
125130
try {

0 commit comments

Comments
 (0)