From 74f538dd629c83ac846b9d2b97f3d11c421c2186 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Arnaud=20Cogolu=C3=A8gnes?=
 <514737+acogoluegnes@users.noreply.github.com>
Date: Wed, 30 Jul 2025 16:44:50 +0200
Subject: [PATCH] Add Netty-based frame handler
This commit adds a Netty-based frame handler. All network IO are based
on Netty when this frame handler is in use. The client library can
benefit of all the flexibility and advantages of Netty: simple API,
pluggable IO layer (Java NIO by default, or e.g. native Epoll on Linux).
The Netty frame handler deprecates the internal one using Java NIO.
The blocking IO frame handler is still the default one in 5.x. The
Netty frame handler should be the only one in 6.x.
Fixes #1664
---
 .github/workflows/test-rabbitmq-alphas.yml    |    6 +-
 .../test-supported-java-versions-main.yml     |    6 +-
 .github/workflows/test.yml                    |    7 +-
 pom.xml                                       |   59 +-
 .../rabbitmq/client/ConnectionFactory.java    | 3324 +++++++++--------
 .../client/SocketChannelConfigurator.java     |    5 +
 .../client/SocketChannelConfigurators.java    |    2 +
 .../client/SslEngineConfigurator.java         |    5 +
 .../client/SslEngineConfigurators.java        |    2 +
 .../rabbitmq/client/impl/AMQConnection.java   |   16 +-
 .../client/impl/DefaultHeartbeatSender.java   |  147 +
 .../java/com/rabbitmq/client/impl/Frame.java  |   30 +-
 .../rabbitmq/client/impl/FrameHandler.java    |    9 +
 .../rabbitmq/client/impl/HeartbeatSender.java |  151 +-
 .../client/impl/NettyFrameHandlerFactory.java |  532 +++
 .../java/com/rabbitmq/client/impl/Utils.java  |   45 +-
 .../rabbitmq/client/impl/nio/NioContext.java  |    2 +
 .../rabbitmq/client/impl/nio/NioParams.java   |    4 +
 .../rabbitmq/client/impl/nio/NioQueue.java    |    2 +
 .../client/AmqpClientTestExtension.java       |  119 +-
 .../AMQConnectionRefreshCredentialsTest.java  |    5 +-
 .../client/test/BlockedConnectionTest.java    |   13 +-
 .../rabbitmq/client/test/BrokerTestCase.java  |    2 +-
 .../rabbitmq/client/test/ClientTestSuite.java |    4 +-
 .../com/rabbitmq/client/test/FrameTest.java   |    9 +-
 .../com/rabbitmq/client/test/NettyTest.java   |  143 +
 ...NoAutoRecoveryWhenTcpWindowIsFullTest.java |    2 +-
 .../client/test/ProtocolVersionMismatch.java  |   92 +
 .../com/rabbitmq/client/test/TestUtils.java   |  980 ++---
 .../client/test/functional/FrameMax.java      |   86 +-
 .../test/functional/FunctionalTestSuite.java  |  112 +-
 .../client/test/functional/Heartbeat.java     |   71 +-
 .../test/functional/UnexpectedFrames.java     |    6 +-
 .../test/ssl/BadVerifiedConnection.java       |    2 +
 .../client/test/ssl/HostnameVerification.java |   19 +-
 .../test/{ => ssl}/SslContextFactoryTest.java |   44 +-
 .../client/test/ssl/SslTestSuite.java         |    2 -
 .../client/test/ssl/TlsConnectionLogging.java |   43 +-
 .../client/test/ssl/TlsTestUtils.java         |   45 +
 .../client/test/ssl/UnverifiedConnection.java |    3 +
 .../client/test/ssl/VerifiedConnection.java   |   54 +-
 src/test/resources/logback-test.xml           |    3 +-
 42 files changed, 3755 insertions(+), 2458 deletions(-)
 create mode 100644 src/main/java/com/rabbitmq/client/impl/DefaultHeartbeatSender.java
 create mode 100644 src/main/java/com/rabbitmq/client/impl/NettyFrameHandlerFactory.java
 create mode 100644 src/test/java/com/rabbitmq/client/test/NettyTest.java
 create mode 100644 src/test/java/com/rabbitmq/client/test/ProtocolVersionMismatch.java
 rename src/test/java/com/rabbitmq/client/test/{ => ssl}/SslContextFactoryTest.java (74%)
diff --git a/.github/workflows/test-rabbitmq-alphas.yml b/.github/workflows/test-rabbitmq-alphas.yml
index 6fe31dfcb7..700e3e32b8 100644
--- a/.github/workflows/test-rabbitmq-alphas.yml
+++ b/.github/workflows/test-rabbitmq-alphas.yml
@@ -43,9 +43,9 @@ jobs:
           RABBITMQ_IMAGE: ${{ matrix.rabbitmq-image }}
       - name: Get dependencies
         run: make deps
-      - name: Test with NIO
+      - name: Test with Netty
         run: |
-          ./mvnw verify -P use-nio -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
+          ./mvnw verify -Dio.layer=netty -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
             -Dtest-broker.A.nodename=rabbit@node0 -Dtest-broker.B.nodename=rabbit@node1 \
             -Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
             -Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
@@ -53,7 +53,7 @@ jobs:
             --no-transfer-progress
       - name: Test with blocking IO
         run: |
-          ./mvnw verify -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
+          ./mvnw verify -Dio.layer=socket -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
             -Dtest-broker.A.nodename=rabbit@node0 -Dtest-broker.B.nodename=rabbit@node1 \
             -Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
             -Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
diff --git a/.github/workflows/test-supported-java-versions-main.yml b/.github/workflows/test-supported-java-versions-main.yml
index 8acb19cb30..6375118d92 100644
--- a/.github/workflows/test-supported-java-versions-main.yml
+++ b/.github/workflows/test-supported-java-versions-main.yml
@@ -39,9 +39,9 @@ jobs:
         run: make deps
       - name: Show version
         run: ./mvnw --version
-      - name: Test with NIO
+      - name: Test with Netty
         run: |
-          ./mvnw verify -P use-nio -Drabbitmqctl.bin=DOCKER:rabbitmq \
+          ./mvnw verify -Dio.layer=netty -Drabbitmqctl.bin=DOCKER:rabbitmq \
             -Dtest-broker.A.nodename=rabbit@$(hostname) -Dmaven.javadoc.skip=true \
             -Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
             -Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
@@ -50,7 +50,7 @@ jobs:
             -Dnet.bytebuddy.experimental=true
       - name: Test with blocking IO
         run: |
-          ./mvnw verify -Drabbitmqctl.bin=DOCKER:rabbitmq \
+          ./mvnw verify -Dio.layer=socket -Drabbitmqctl.bin=DOCKER:rabbitmq \
             -Dtest-broker.A.nodename=rabbit@$(hostname) -Dmaven.javadoc.skip=true \
             -Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
             -Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 512b5f2054..6a93eb453a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -39,9 +39,9 @@ jobs:
         run: ci/start-cluster.sh
       - name: Get dependencies
         run: make deps
-      - name: Test with NIO
+      - name: Test with Netty
         run: |
-          ./mvnw verify -P use-nio -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
+          ./mvnw verify -Dio.layer=netty -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
             -Dtest-broker.A.nodename=rabbit@node0 -Dtest-broker.B.nodename=rabbit@node1 \
             -Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
             -Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
@@ -49,12 +49,11 @@ jobs:
             --no-transfer-progress
       - name: Test with blocking IO
         run: |
-          ./mvnw verify -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
+          ./mvnw verify -Dio.layer=socket -Drabbitmqctl.bin=DOCKER:rabbitmq0 \
             -Dtest-broker.A.nodename=rabbit@node0 -Dtest-broker.B.nodename=rabbit@node1 \
             -Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
             -Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
             -Dmaven.javadoc.skip=true \
-            -Dtest-client-cert.password= -Dtest-tls-certs.dir=rabbitmq-configuration/tls \
             --no-transfer-progress
       - name: Stop cluster
         run: docker compose --file ci/cluster/docker-compose.yml down
diff --git a/pom.xml b/pom.xml
index a893add022..5f9cb96901 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,6 +56,7 @@
 
     true
     1.7.36
+    4.2.3.Final
     4.2.33
     1.15.2
     1.52.0
@@ -245,30 +246,6 @@
       
     
 
-    
-    
-      use-nio
-      
-        
-          
-            org.apache.maven.plugins
-            maven-failsafe-plugin
-            ${maven.failsafe.plugin.version}
-            
-              
-                true
-                true
-              
-              ${test-arguments}
-            
-          
-        
-      
-    
-