You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ta...@apache.org on 2024/09/19 22:15:56 UTC
(qpid-protonj2) branch main updated: PROTON-2852 Remove the experimental Netty 5 support
This is an automated email from the ASF dual-hosted git repository.
tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-protonj2.git
The following commit(s) were added to refs/heads/main by this push:
new 198debab PROTON-2852 Remove the experimental Netty 5 support
198debab is described below
commit 198debab8a12c78b6736e4fe1a796136b33ec852
Author: Timothy Bish <ta...@gmail.com>
AuthorDate: Thu Sep 19 18:11:35 2024 -0400
PROTON-2852 Remove the experimental Netty 5 support
Removes current experimental Netty 5 code as that has stopped evolving
and current code won't work with the long unreleased netty 5 branch
code.
---
pom.xml | 44 -
protonj2-client/pom.xml | 38 -
.../qpid/protonj2/client/transport/IOContext.java | 4 -
.../client/transport/netty5/EpollSupport.java | 54 -
.../client/transport/netty5/IOUringSupport.java | 52 -
.../client/transport/netty5/KQueueSupport.java | 54 -
.../client/transport/netty5/Netty5IOContext.java | 195 ---
.../client/transport/netty5/Netty5Support.java | 48 -
.../client/transport/netty5/SslSupport.java | 474 ------
.../client/transport/netty5/TcpTransport.java | 536 -------
.../transport/netty5/WebSocketTransport.java | 222 ---
.../client/impl/ReconnectStreamReceiverTest.java | 1 -
.../protonj2/client/impl/SslConnectionTest.java | 4 +-
.../transport/netty5/NettyBlackHoleServer.java | 52 -
.../client/transport/netty5/NettyEchoServer.java | 53 -
.../transport/netty5/NettyIOContextTest.java | 50 -
.../client/transport/netty5/NettyServer.java | 410 -----
.../transport/netty5/OpenSslTransportTest.java | 222 ---
.../netty5/SecureWebSocketTransportTest.java | 71 -
.../client/transport/netty5/SslSupportTest.java | 1020 -------------
.../client/transport/netty5/SslTransportTest.java | 435 ------
.../client/transport/netty5/TcpTransportTest.java | 1196 ---------------
.../transport/netty5/WebSocketTransportTest.java | 504 -------
.../transport/netty5/X509AliasKeyManagerTest.java | 149 --
protonj2-test-driver/pom.xml | 26 -
.../protonj2/test/driver/netty/NettyIOBuilder.java | 7 -
.../test/driver/netty/netty5/Netty5Client.java | 564 -------
.../test/driver/netty/netty5/Netty5EventLoop.java | 48 -
.../test/driver/netty/netty5/Netty5Server.java | 580 -------
.../test/driver/netty/netty5/Netty5Support.java | 48 -
.../test/driver/netty/netty5/SslSupport.java | 498 ------
protonj2/pom.xml | 5 -
.../buffer/netty/Netty5ProtonBufferAllocator.java | 139 --
.../buffer/netty/Netty5ToProtonBufferAdapter.java | 985 ------------
.../buffer/netty/ProtonBufferToNetty5Adapter.java | 1107 --------------
.../protonj2/buffer/ProtonAbstractBufferTest.java | 11 -
.../buffer/impl/ProtonCompositeBufferImplTest.java | 10 +-
.../netty/Netty5ProtonBufferAdapterTest.java | 72 -
.../netty/ProtonBufferToNetty5AdapterTest.java | 1596 --------------------
39 files changed, 7 insertions(+), 11577 deletions(-)
diff --git a/pom.xml b/pom.xml
index f6e51765..e912a7b8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,7 +48,6 @@
<hamcrest.version>3.0</hamcrest.version>
<netty.version>4.1.113.Final</netty.version>
<netty.iouring.version>0.0.25.Final</netty.iouring.version>
- <netty5.version>5.0.0.Alpha5</netty5.version>
<netty.tcnative.version>2.0.66.Final</netty.tcnative.version>
<!-- Plugin versions -->
@@ -64,11 +63,6 @@
<netty-transport-native-epoll-classifier>linux-x86_64</netty-transport-native-epoll-classifier>
<netty-transport-native-kqueue-classifier>osx-x86_64</netty-transport-native-kqueue-classifier>
- <netty5-scope>provided</netty5-scope>
- <netty5-transport-native-io-uring-classifier>linux-x86_64</netty5-transport-native-io-uring-classifier>
- <netty5-transport-native-epoll-classifier>linux-x86_64</netty5-transport-native-epoll-classifier>
- <netty5-transport-native-kqueue-classifier>osx-x86_64</netty5-transport-native-kqueue-classifier>
-
<!-- surefire forked jvm arguments -->
<argLine>-Xmx2g -enableassertions ${jacoco-config}</argLine>
@@ -170,44 +164,6 @@
<version>${netty.iouring.version}</version>
<classifier>${netty-transport-native-io-uring-classifier}</classifier>
</dependency>
- <!-- Netty 5 Dependencies-->
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-buffer</artifactId>
- <version>${netty5.version}</version>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-common</artifactId>
- <version>${netty5.version}</version>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-handler</artifactId>
- <version>${netty5.version}</version>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-transport</artifactId>
- <version>${netty5.version}</version>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-codec-http</artifactId>
- <version>${netty5.version}</version>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-transport-native-epoll</artifactId>
- <version>${netty5.version}</version>
- <classifier>${netty-transport-native-epoll-classifier}</classifier>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-transport-native-kqueue</artifactId>
- <version>${netty5.version}</version>
- <classifier>${netty-transport-native-kqueue-classifier}</classifier>
- </dependency>
<!-- Testing only Uber Jar inclusion -->
<dependency>
<groupId>io.netty</groupId>
diff --git a/protonj2-client/pom.xml b/protonj2-client/pom.xml
index cb58e7b0..a3f90520 100644
--- a/protonj2-client/pom.xml
+++ b/protonj2-client/pom.xml
@@ -83,44 +83,6 @@
<classifier>${netty-transport-native-kqueue-classifier}</classifier>
<scope>${netty-scope}</scope>
</dependency>
- <!-- Netty 5 Development dependencies -->
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-buffer</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-common</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-handler</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-transport</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-codec-http</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-transport-native-epoll</artifactId>
- <classifier>${netty-transport-native-epoll-classifier}</classifier>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-transport-native-kqueue</artifactId>
- <classifier>${netty5-transport-native-kqueue-classifier}</classifier>
- <scope>${netty5-scope}</scope>
- </dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/IOContext.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/IOContext.java
index 22c9e52a..c4f725a9 100644
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/IOContext.java
+++ b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/IOContext.java
@@ -21,8 +21,6 @@ import org.apache.qpid.protonj2.client.SslOptions;
import org.apache.qpid.protonj2.client.TransportOptions;
import org.apache.qpid.protonj2.client.transport.netty4.Netty4IOContext;
import org.apache.qpid.protonj2.client.transport.netty4.Netty4Support;
-import org.apache.qpid.protonj2.client.transport.netty5.Netty5IOContext;
-import org.apache.qpid.protonj2.client.transport.netty5.Netty5Support;
import org.apache.qpid.protonj2.engine.Scheduler;
/**
@@ -69,8 +67,6 @@ public interface IOContext {
static IOContext create(TransportOptions options, SslOptions sslOptions, String ioThreadName) {
if (Netty4Support.isAvailable()) {
return new Netty4IOContext(options, sslOptions, ioThreadName);
- } else if (Netty5Support.isAvailable()) {
- return new Netty5IOContext(options, sslOptions, ioThreadName);
}
throw new UnsupportedOperationException("Netty not available on the class path");
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/EpollSupport.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/EpollSupport.java
deleted file mode 100644
index 2b774d92..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/EpollSupport.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.util.concurrent.ThreadFactory;
-
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.channel.Channel;
-import io.netty5.channel.EventLoopGroup;
-import io.netty5.channel.MultithreadEventLoopGroup;
-import io.netty5.channel.epoll.Epoll;
-import io.netty5.channel.epoll.EpollHandler;
-import io.netty5.channel.epoll.EpollSocketChannel;
-
-public final class EpollSupport {
-
- private static final Logger LOG = LoggerFactory.getLogger(EpollSupport.class);
-
- public static final String NAME = "EPOLL";
-
- public static boolean isAvailable(TransportOptions transportOptions) {
- try {
- return transportOptions.allowNativeIO() && Epoll.isAvailable();
- } catch (NoClassDefFoundError ncdfe) {
- LOG.debug("Unable to check for Epoll support due to missing class definition", ncdfe);
- return false;
- }
- }
-
- public static EventLoopGroup createGroup(int nThreads, ThreadFactory ioThreadFactory) {
- return new MultithreadEventLoopGroup(nThreads, ioThreadFactory, EpollHandler.newFactory());
- }
-
- public static Class<? extends Channel> getChannelClass() {
- return EpollSocketChannel.class;
- }
-}
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/IOUringSupport.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/IOUringSupport.java
deleted file mode 100644
index 7a435e14..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/IOUringSupport.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.util.concurrent.ThreadFactory;
-
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.channel.Channel;
-import io.netty5.channel.EventLoopGroup;
-
-public class IOUringSupport {
-
- private static final Logger LOG = LoggerFactory.getLogger(IOUringSupport.class);
-
- public static final String NAME = "IO_URING";
-
- public static boolean isAvailable(TransportOptions transportOptions) {
- try {
- return false; //transportOptions.allowNativeIO() && IOUring.isAvailable();
- } catch (NoClassDefFoundError ncdfe) {
- LOG.debug("Unable to check for IO_Uring support due to missing class definition", ncdfe);
- return false;
- }
- }
-
- public static EventLoopGroup createGroup(int nThreads, ThreadFactory ioThreadFactory) {
- // return new MultithreadEventLoopGroup(nThreads, ioThreadFactory, null);
- throw new UnsupportedOperationException("Netty v5 doesn't yet support IO_Uring");
- }
-
- public static Class<? extends Channel> getChannelClass() {
- // return IOUringSocketChannel.class;
- throw new UnsupportedOperationException("Netty v5 doesn't yet support IO_Uring");
- }
-}
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/KQueueSupport.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/KQueueSupport.java
deleted file mode 100644
index 7c4fd76e..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/KQueueSupport.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.util.concurrent.ThreadFactory;
-
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.channel.Channel;
-import io.netty5.channel.EventLoopGroup;
-import io.netty5.channel.MultithreadEventLoopGroup;
-import io.netty5.channel.kqueue.KQueue;
-import io.netty5.channel.kqueue.KQueueHandler;
-import io.netty5.channel.kqueue.KQueueSocketChannel;
-
-public final class KQueueSupport {
-
- private static final Logger LOG = LoggerFactory.getLogger(KQueueSupport.class);
-
- public static final String NAME = "KQUEUE";
-
- public static boolean isAvailable(TransportOptions transportOptions) {
- try {
- return transportOptions.allowNativeIO() && KQueue.isAvailable();
- } catch (NoClassDefFoundError ncdfe) {
- LOG.debug("Unable to check for KQueue support due to missing class definition", ncdfe);
- return false;
- }
- }
-
- public static EventLoopGroup createGroup(int nThreads, ThreadFactory ioThreadFactory) {
- return new MultithreadEventLoopGroup(nThreads, ioThreadFactory, KQueueHandler.newFactory());
- }
-
- public static Class<? extends Channel> getChannelClass() {
- return KQueueSocketChannel.class;
- }
-}
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/Netty5IOContext.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/Netty5IOContext.java
deleted file mode 100644
index cffa2187..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/Netty5IOContext.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.util.Objects;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Future;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.apache.qpid.protonj2.client.transport.IOContext;
-import org.apache.qpid.protonj2.client.util.TrackableThreadFactory;
-import org.apache.qpid.protonj2.engine.Scheduler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.bootstrap.Bootstrap;
-import io.netty5.channel.Channel;
-import io.netty5.channel.EventLoopGroup;
-import io.netty5.channel.MultithreadEventLoopGroup;
-import io.netty5.channel.nio.NioHandler;
-import io.netty5.channel.socket.nio.NioSocketChannel;
-
-/**
- * Builder of Transport instances that will validate the build options and produce a
- * correctly configured transport based on the options set.
- */
-public final class Netty5IOContext implements IOContext {
-
- private static final Logger LOG = LoggerFactory.getLogger(Netty5IOContext.class);
-
- private static final int SHUTDOWN_TIMEOUT = 50;
- private static final int ASYNC_SHUTDOWN_TIMEOUT = 100;
- private static final int ASYNC_SHUTDOWN_QUIET_PERIOD = 10;
-
- private final EventLoopGroup group;
- private final NettyIOScheduler scheduler = new NettyIOScheduler();
- private final Class<? extends Channel> channelClass;
- private final TransportOptions options;
- private final SslOptions sslOptions;
- private final ThreadFactory threadFactory;
-
- public Netty5IOContext(TransportOptions options, SslOptions ssl, String ioThreadName) {
- Objects.requireNonNull(options, "Transport Options cannot be null");
- Objects.requireNonNull(ssl, "Transport SSL Options cannot be null");
-
- this.options = options;
- this.sslOptions = ssl;
- this.threadFactory = new TrackableThreadFactory(ioThreadName, true);
-
- final String[] nativeIOPreference = options.nativeIOPreference();
-
- EventLoopGroup selectedGroup = null;
- Class<? extends Channel> selectedChannelClass = null;
-
- if (options.allowNativeIO()) {
- for (String nativeID : nativeIOPreference) {
- if (EpollSupport.NAME.equalsIgnoreCase(nativeID)) {
- if (EpollSupport.isAvailable(options)) {
- LOG.trace("Netty Transports will be using Epoll mode");
- selectedGroup = EpollSupport.createGroup(1, threadFactory);
- selectedChannelClass = EpollSupport.getChannelClass();
- break;
- }
- } else if (IOUringSupport.NAME.equalsIgnoreCase(nativeID)) {
- if (IOUringSupport.isAvailable(options)) {
- LOG.trace("Netty Transports will be using IO-Uring mode");
- selectedGroup = IOUringSupport.createGroup(1, threadFactory);
- selectedChannelClass = IOUringSupport.getChannelClass();
- break;
- }
- } else if (KQueueSupport.NAME.equalsIgnoreCase(nativeID)) {
- if (KQueueSupport.isAvailable(options)) {
- LOG.trace("Netty Transports will be using KQueue mode");
- selectedGroup = KQueueSupport.createGroup(1, threadFactory);
- selectedChannelClass = KQueueSupport.getChannelClass();
- break;
- }
- } else {
- throw new IllegalArgumentException(
- String.format("Provided preferred native transport type name: %s, is not supported.", nativeID));
- }
- }
- }
-
- if (selectedGroup == null) {
- LOG.trace("Netty Transports will be using NIO mode");
- selectedGroup = new MultithreadEventLoopGroup(1, threadFactory, NioHandler.newFactory());
- selectedChannelClass = NioSocketChannel.class;
- }
-
- this.group = selectedGroup;
- this.channelClass = selectedChannelClass;
- }
-
- @Override
- public void shutdown() {
- if (!group.isShutdown()) {
- group.shutdownGracefully(0, SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
- try {
- if (!group.awaitTermination(2 * SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS)) {
- LOG.trace("Connection IO Event Loop shutdown failed to complete in allotted time");
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- /**
- * Shutdown the event loop asynchronously with a grace period for work that might be in-bound
- * at the time of termination. This is safe to call from inside the event loop where the
- * standard blocking shutdown API is not.
- */
- @Override
- public void shutdownAsync() {
- if (!group.isShutdown()) {
- group.shutdownGracefully(ASYNC_SHUTDOWN_QUIET_PERIOD, ASYNC_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
- }
- }
-
- @Override
- public Scheduler ioScheduler() {
- return scheduler;
- }
-
- @Override
- public TcpTransport newTransport() {
- if (group.isShutdown() || group.isShuttingDown() || group.isTerminated()) {
- throw new IllegalStateException("Cannot create a Transport from a shutdown IO context");
- }
-
- final Bootstrap bootstrap = new Bootstrap().channel(channelClass).group(group);
-
- final TcpTransport transport;
-
- if (options.useWebSockets()) {
- transport = new WebSocketTransport(bootstrap, options, sslOptions);
- } else {
- transport = new TcpTransport(bootstrap, options, sslOptions);
- }
-
- return transport;
- }
-
- public class NettyIOScheduler implements Scheduler, Executor {
-
- @Override
- public void execute(Runnable command) {
- group.execute(command);
- }
-
- @Override
- public Future<?> schedule(Runnable command, long delay, TimeUnit unit) {
- return group.schedule(command, delay, unit).asStage();
- }
-
- @Override
- public <V> Future<V> schedule(Callable<V> task, long delay, TimeUnit unit) {
- return group.schedule(task, delay, unit).asStage();
- }
-
- @Override
- public Future<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
- return group.scheduleAtFixedRate(command, initialDelay, period, unit).asStage();
- }
-
- @Override
- public Future<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
- return group.scheduleWithFixedDelay(command, initialDelay, delay, unit).asStage();
- }
-
- @Override
- public boolean isShutdown() {
- return group.isShutdown();
- }
- }
-}
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/Netty5Support.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/Netty5Support.java
deleted file mode 100644
index 1bb8ac87..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/Netty5Support.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.buffer.BufferAllocator;
-
-/**
- * Support class used to detect if Netty 5 is available on the class path.
- */
-public final class Netty5Support {
-
- private static final Logger LOG = LoggerFactory.getLogger(Netty5Support.class);
-
- private static final Throwable UNAVAILABILITY_CAUSE;
- static {
- Throwable cause = null;
- try {
- BufferAllocator.onHeapUnpooled();
- } catch (Throwable ex) {
- LOG.debug("Netty 5 not available for use.");
- cause = ex;
- }
-
- UNAVAILABILITY_CAUSE = cause;
- }
-
- public static final boolean isAvailable() {
- return UNAVAILABILITY_CAUSE == null;
- }
-}
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupport.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupport.java
deleted file mode 100644
index 4d1ffe3c..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupport.java
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509ExtendedKeyManager;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.transport.X509AliasKeyManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.buffer.BufferAllocator;
-import io.netty5.handler.ssl.OpenSsl;
-import io.netty5.handler.ssl.OpenSslX509KeyManagerFactory;
-import io.netty5.handler.ssl.SslContext;
-import io.netty5.handler.ssl.SslContextBuilder;
-import io.netty5.handler.ssl.SslHandler;
-import io.netty5.handler.ssl.SslProvider;
-import io.netty5.handler.ssl.util.InsecureTrustManagerFactory;
-
-/**
- * Static class that provides various utility methods used by Transport implementations.
- */
-public final class SslSupport {
-
- private static final Logger LOG = LoggerFactory.getLogger(SslSupport.class);
-
- public static final String FROM_CLASSPATH_PREFIX = "classpath:";
- public static final String FROM_FILE_PREFIX = "file:";
- public static final String FROM_FILE_URL_PREFIX = "file://";
-
- /**
- * Determines if Netty OpenSSL support is available and applicable based on the configuration
- * in the given TransportOptions instance.
- *
- * @param options
- * The configuration of the Transport being created.
- *
- * @return true if OpenSSL support is available and usable given the requested configuration.
- */
- public static boolean isOpenSSLPossible(SslOptions options) {
- boolean result = false;
-
- if (options.allowNativeSSL()) {
- if (!OpenSsl.isAvailable()) {
- LOG.debug("OpenSSL could not be enabled because a suitable implementation could not be found.", OpenSsl.unavailabilityCause());
- } else if (options.sslContextOverride() != null) {
- LOG.debug("OpenSSL could not be enabled due to user SSLContext being supplied.");
- } else if (!OpenSsl.supportsKeyManagerFactory()) {
- LOG.debug("OpenSSL could not be enabled because the version provided does not allow a KeyManagerFactory to be used.");
- } else if (options.keyAlias() != null) {
- LOG.debug("OpenSSL could not be enabled because a keyAlias is set and that feature is not supported for OpenSSL.");
- } else {
- LOG.debug("OpenSSL Enabled: Version {} of OpenSSL will be used", OpenSsl.versionString());
- result = true;
- }
- }
-
- return result;
- }
-
- /**
- * Creates a Netty SslHandler instance for use in Transports that require
- * an SSL encoder / decoder.
- *
- * If the given options contain an SSLContext override, this will be used directly
- * when creating the handler. If they do not, an SSLContext will first be created
- * using the other option values.
- *
- * @param allocator
- * The Netty Buffer Allocator to use when Netty resources need to be created.
- * @param host
- * the host name or IP address that this transport connects to.
- * @param port
- * the port on the given host that this transport connects to.
- * @param options
- * The SSL options object to build the SslHandler instance from.
- *
- * @return a new SslHandler that is configured from the given options.
- *
- * @throws Exception if an error occurs while creating the SslHandler instance.
- */
- public static SslHandler createSslHandler(BufferAllocator allocator, String host, int port, SslOptions options) throws Exception {
- final SSLEngine sslEngine;
-
- if (isOpenSSLPossible(options)) {
- SslContext sslContext = createOpenSslContext(options);
- sslEngine = createOpenSslEngine(allocator, host, port, sslContext, options);
- } else {
- SSLContext sslContext = options.sslContextOverride();
- if (sslContext == null) {
- sslContext = createJdkSslContext(options);
- }
-
- sslEngine = createJdkSslEngine(host, port, sslContext, options);
- }
-
- return new SslHandler(sslEngine);
- }
-
- //----- JDK SSL Support Methods ------------------------------------------//
-
- /**
- * Create a new SSLContext using the options specific in the given TransportOptions
- * instance.
- *
- * @param options
- * the configured options used to create the SSLContext.
- *
- * @return a new SSLContext instance.
- *
- * @throws Exception if an error occurs while creating the context.
- */
- public static SSLContext createJdkSslContext(SslOptions options) throws Exception {
- try {
- String contextProtocol = options.contextProtocol();
- LOG.trace("Getting SSLContext instance using protocol: {}", contextProtocol);
-
- SSLContext context = SSLContext.getInstance(contextProtocol);
-
- KeyManager[] keyMgrs = loadKeyManagers(options);
- TrustManager[] trustManagers = loadTrustManagers(options);
-
- context.init(keyMgrs, trustManagers, new SecureRandom());
- return context;
- } catch (Exception e) {
- LOG.error("Failed to create SSLContext: {}", e, e);
- throw e;
- }
- }
-
- /**
- * Create a new JDK SSLEngine instance in client mode from the given SSLContext and
- * TransportOptions instances.
- *
- * @param host
- * the host name or IP address that this transport connects to.
- * @param port
- * the port on the given host that this transport connects to.
- * @param context
- * the SSLContext to use when creating the engine.
- * @param options
- * the TransportOptions to use to configure the new SSLEngine.
- *
- * @return a new SSLEngine instance in client mode.
- *
- * @throws Exception if an error occurs while creating the new SSLEngine.
- */
- public static SSLEngine createJdkSslEngine(String host, int port, SSLContext context, SslOptions options) throws Exception {
- SSLEngine engine = null;
- if (host == null || host.isEmpty()) {
- engine = context.createSSLEngine();
- } else {
- engine = context.createSSLEngine(host, port);
- }
-
- engine.setEnabledProtocols(buildEnabledProtocols(engine, options));
- engine.setEnabledCipherSuites(buildEnabledCipherSuites(engine, options));
- engine.setUseClientMode(true);
-
- if (options.verifyHost()) {
- SSLParameters sslParameters = engine.getSSLParameters();
- sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
- engine.setSSLParameters(sslParameters);
- }
-
- return engine;
- }
-
- //----- OpenSSL Support Methods ------------------------------------------//
-
- /**
- * Create a new Netty SslContext using the options specific in the given TransportOptions
- * instance.
- *
- * @param options
- * the configured options used to create the SslContext.
- *
- * @return a new SslContext instance.
- *
- * @throws Exception if an error occurs while creating the context.
- */
- public static SslContext createOpenSslContext(SslOptions options) throws Exception {
- try {
- String contextProtocol = options.contextProtocol();
- LOG.trace("Getting SslContext instance using protocol: {}", contextProtocol);
-
- KeyManagerFactory keyManagerFactory = loadKeyManagerFactory(options, SslProvider.OPENSSL);
- TrustManagerFactory trustManagerFactory = loadTrustManagerFactory(options);
- SslContextBuilder builder = SslContextBuilder.forClient().sslProvider(SslProvider.OPENSSL);
-
- // TODO - There is oddly no way in Netty right now to get the set of supported protocols
- // when creating the SslContext or really even when creating the SSLEngine. Seems
- // like an oversight, for now we call it with TLSv1.2 so it looks like we did something.
- if (options.contextProtocol().equals(SslOptions.DEFAULT_CONTEXT_PROTOCOL)) {
- builder.protocols("TLSv1.2");
- } else {
- builder.protocols(options.contextProtocol());
- }
- builder.keyManager(keyManagerFactory);
- builder.trustManager(trustManagerFactory);
-
- return builder.build();
- } catch (Exception e) {
- LOG.error("Failed to create SslContext: {}", e, e);
- throw e;
- }
- }
-
- /**
- * Create a new OpenSSL SSLEngine instance in client mode from the given SSLContext and
- * TransportOptions instances.
- *
- * @param allocator
- * the Netty BufferAllocator to use to create the OpenSSL engine
- * @param host
- * the host name or IP address that this transport connects to.
- * @param port
- * the port on the given host that this transport connects to.
- * @param context
- * the Netty SslContext to use when creating the engine.
- * @param options
- * the TransportOptions to use to configure the new SSLEngine.
- *
- * @return a new Netty managed SSLEngine instance in client mode.
- *
- * @throws Exception if an error occurs while creating the new SSLEngine.
- */
- public static SSLEngine createOpenSslEngine(BufferAllocator allocator, String host, int port, SslContext context, SslOptions options) throws Exception {
- SSLEngine engine = null;
-
- if (allocator == null) {
- throw new IllegalArgumentException("OpenSSL engine requires a valid ByteBufAllocator to operate");
- }
-
- if (host == null || host.isEmpty()) {
- engine = context.newEngine(allocator);
- } else {
- engine = context.newEngine(allocator, host, port);
- }
-
- engine.setEnabledProtocols(buildEnabledProtocols(engine, options));
- engine.setEnabledCipherSuites(buildEnabledCipherSuites(engine, options));
- engine.setUseClientMode(true);
-
- if (options.verifyHost()) {
- SSLParameters sslParameters = engine.getSSLParameters();
- sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
- engine.setSSLParameters(sslParameters);
- }
-
- return engine;
- }
-
- //----- Internal support methods -----------------------------------------//
-
- private static String[] buildEnabledProtocols(SSLEngine engine, SslOptions options) {
- List<String> enabledProtocols = new ArrayList<String>();
-
- if (options.enabledProtocols() != null) {
- List<String> configuredProtocols = Arrays.asList(options.enabledProtocols());
- LOG.trace("Configured protocols from transport options: {}", configuredProtocols);
- enabledProtocols.addAll(configuredProtocols);
- } else {
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- LOG.trace("Default protocols from the SSLEngine: {}", engineProtocols);
- enabledProtocols.addAll(engineProtocols);
- }
-
- String[] disabledProtocols = options.disabledProtocols();
- if (disabledProtocols != null) {
- List<String> disabled = Arrays.asList(disabledProtocols);
- LOG.trace("Disabled protocols: {}", disabled);
- enabledProtocols.removeAll(disabled);
- }
-
- LOG.trace("Enabled protocols: {}", enabledProtocols);
-
- return enabledProtocols.toArray(new String[0]);
- }
-
- private static String[] buildEnabledCipherSuites(SSLEngine engine, SslOptions options) {
- List<String> enabledCipherSuites = new ArrayList<String>();
-
- if (options.enabledCipherSuites() != null) {
- List<String> configuredCipherSuites = Arrays.asList(options.enabledCipherSuites());
- LOG.trace("Configured cipher suites from transport options: {}", configuredCipherSuites);
- enabledCipherSuites.addAll(configuredCipherSuites);
- } else {
- List<String> engineCipherSuites = Arrays.asList(engine.getEnabledCipherSuites());
- LOG.trace("Default cipher suites from the SSLEngine: {}", engineCipherSuites);
- enabledCipherSuites.addAll(engineCipherSuites);
- }
-
- String[] disabledCipherSuites = options.disabledCipherSuites();
- if (disabledCipherSuites != null) {
- List<String> disabled = Arrays.asList(disabledCipherSuites);
- LOG.trace("Disabled cipher suites: {}", disabled);
- enabledCipherSuites.removeAll(disabled);
- }
-
- LOG.trace("Enabled cipher suites: {}", enabledCipherSuites);
-
- return enabledCipherSuites.toArray(new String[0]);
- }
-
- private static TrustManager[] loadTrustManagers(SslOptions options) throws Exception {
- TrustManagerFactory factory = loadTrustManagerFactory(options);
- if (factory != null) {
- return factory.getTrustManagers();
- } else {
- return null;
- }
- }
-
- private static TrustManagerFactory loadTrustManagerFactory(SslOptions options) throws Exception {
- if (options.trustAll()) {
- return InsecureTrustManagerFactory.INSTANCE;
- }
-
- if (options.trustStoreLocation() == null) {
- return null;
- }
-
- TrustManagerFactory fact = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-
- String storeLocation = options.trustStoreLocation();
- String storePassword = options.trustStorePassword();
- String storeType = options.trustStoreType();
-
- LOG.trace("Attempt to load TrustStore from location {} of type {}", storeLocation, storeType);
-
- KeyStore trustStore = loadStore(storeLocation, storePassword, storeType);
- fact.init(trustStore);
-
- return fact;
- }
-
- private static KeyManager[] loadKeyManagers(SslOptions options) throws Exception {
- if (options.keyStoreLocation() == null) {
- return null;
- }
-
- KeyManagerFactory fact = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-
- String storeLocation = options.keyStoreLocation();
- String storePassword = options.keyStorePassword();
- String storeType = options.keyStoreType();
- String alias = options.keyAlias();
-
- LOG.trace("Attempt to load KeyStore from location {} of type {}", storeLocation, storeType);
-
- KeyStore keyStore = loadStore(storeLocation, storePassword, storeType);
- fact.init(keyStore, storePassword != null ? storePassword.toCharArray() : null);
-
- if (alias == null) {
- return fact.getKeyManagers();
- } else {
- validateAlias(keyStore, alias);
- return wrapKeyManagers(alias, fact.getKeyManagers());
- }
- }
-
- private static KeyManagerFactory loadKeyManagerFactory(SslOptions options, SslProvider provider) throws Exception {
- if (options.keyStoreLocation() == null) {
- return null;
- }
-
- final KeyManagerFactory factory;
- if (provider.equals(SslProvider.JDK)) {
- factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- } else {
- factory = new OpenSslX509KeyManagerFactory();
- }
-
- String storeLocation = options.keyStoreLocation();
- String storePassword = options.keyStorePassword();
- String storeType = options.keyStoreType();
-
- LOG.trace("Attempt to load KeyStore from location {} of type {}", storeLocation, storeType);
-
- KeyStore keyStore = loadStore(storeLocation, storePassword, storeType);
- factory.init(keyStore, storePassword != null ? storePassword.toCharArray() : null);
-
- return factory;
- }
-
- private static KeyManager[] wrapKeyManagers(String alias, KeyManager[] origKeyManagers) {
- KeyManager[] keyManagers = new KeyManager[origKeyManagers.length];
- for (int i = 0; i < origKeyManagers.length; i++) {
- KeyManager km = origKeyManagers[i];
- if (km instanceof X509ExtendedKeyManager) {
- km = new X509AliasKeyManager(alias, (X509ExtendedKeyManager) km);
- }
-
- keyManagers[i] = km;
- }
-
- return keyManagers;
- }
-
- private static void validateAlias(KeyStore store, String alias) throws IllegalArgumentException, KeyStoreException {
- if (!store.containsAlias(alias)) {
- throw new IllegalArgumentException("The alias '" + alias + "' doesn't exist in the key store");
- }
-
- if (!store.isKeyEntry(alias)) {
- throw new IllegalArgumentException("The alias '" + alias + "' in the keystore doesn't represent a key entry");
- }
- }
-
- private static KeyStore loadStore(String storePath, final String password, String storeType) throws Exception {
- KeyStore store = KeyStore.getInstance(storeType);
- try (InputStream in = openStoreAtLocation(storePath)) {
- store.load(in, password != null ? password.toCharArray() : null);
- } catch (Exception ex) {
- LOG.trace("Caught Error loading store: {}", ex.getMessage(), ex);
- throw ex;
- }
-
- return store;
- }
-
- private static InputStream openStoreAtLocation(final String storePath) throws IOException {
- final InputStream stream;
-
- if (storePath.startsWith(FROM_CLASSPATH_PREFIX)) {
- stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath.substring(FROM_CLASSPATH_PREFIX.length()));
- } else if (storePath.startsWith(FROM_FILE_URL_PREFIX)) {
- stream = new FileInputStream(storePath.substring(FROM_FILE_URL_PREFIX.length()));
- } else if (storePath.startsWith(FROM_FILE_PREFIX)) {
- stream = new FileInputStream(storePath.substring(FROM_FILE_PREFIX.length()));
- } else {
- stream = new FileInputStream(storePath);
- }
-
- if (stream == null) {
- throw new IOException("Could no locate KeyStore at location: " + storePath);
- }
-
- return stream;
- }
-}
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/TcpTransport.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/TcpTransport.java
deleted file mode 100644
index 5fba50b6..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/TcpTransport.java
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.Principal;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.qpid.protonj2.buffer.ProtonBuffer;
-import org.apache.qpid.protonj2.buffer.ProtonBufferAllocator;
-import org.apache.qpid.protonj2.buffer.ProtonBufferComponent;
-import org.apache.qpid.protonj2.buffer.ProtonBufferComponentAccessor;
-import org.apache.qpid.protonj2.buffer.netty.Netty5ProtonBufferAllocator;
-import org.apache.qpid.protonj2.buffer.netty.Netty5ToProtonBufferAdapter;
-import org.apache.qpid.protonj2.buffer.netty.ProtonBufferToNetty5Adapter;
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.apache.qpid.protonj2.client.transport.Transport;
-import org.apache.qpid.protonj2.client.transport.TransportListener;
-import org.apache.qpid.protonj2.client.util.IOExceptionSupport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.bootstrap.Bootstrap;
-import io.netty5.buffer.Buffer;
-import io.netty5.channel.Channel;
-import io.netty5.channel.ChannelHandler;
-import io.netty5.channel.ChannelHandlerContext;
-import io.netty5.channel.ChannelInitializer;
-import io.netty5.channel.ChannelOption;
-import io.netty5.channel.ChannelPipeline;
-import io.netty5.channel.SimpleChannelInboundHandler;
-import io.netty5.handler.logging.LoggingHandler;
-import io.netty5.handler.ssl.SslHandler;
-import io.netty5.util.concurrent.Future;
-import io.netty5.util.concurrent.FutureListener;
-
-/**
- * TCP based transport that uses Netty as the underlying IO layer.
- */
-public class TcpTransport implements Transport {
-
- private static final Logger LOG = LoggerFactory.getLogger(TcpTransport.class);
-
- protected final AtomicBoolean connected = new AtomicBoolean();
- protected final AtomicBoolean closed = new AtomicBoolean();
- protected final CountDownLatch connectedLatch = new CountDownLatch(1);
- protected final TransportOptions options;
- protected final SslOptions sslOptions;
- protected final Bootstrap bootstrap;
-
- protected Channel channel;
- protected volatile IOException failureCause;
- protected String host;
- protected int port;
- protected TransportListener listener;
- protected Netty5ProtonBufferAllocator nettyAllocator;
-
- /**
- * Create a new {@link TcpTransport} instance with the given configuration.
- *
- * @param bootstrap
- * the Netty {@link Bootstrap} that this transport's IO layer is bound to.
- * @param options
- * the {@link TransportOptions} used to configure the socket connection.
- * @param sslOptions
- * the {@link SslOptions} to use if the options indicate SSL is enabled.
- */
- public TcpTransport(Bootstrap bootstrap, TransportOptions options, SslOptions sslOptions) {
- if (options == null) {
- throw new IllegalArgumentException("Transport Options cannot be null");
- }
-
- if (sslOptions == null) {
- throw new IllegalArgumentException("Transport SSL Options cannot be null");
- }
-
- if (bootstrap == null) {
- throw new IllegalArgumentException("A transport must have an assigned Bootstrap before connect.");
- }
-
- this.sslOptions = sslOptions;
- this.options = options;
- this.bootstrap = bootstrap;
- }
-
- @Override
- public TcpTransport connect(String host, int port, TransportListener listener) throws IOException {
- if (closed.get()) {
- throw new IllegalStateException("Transport has already been closed");
- }
-
- if (listener == null) {
- throw new IllegalArgumentException("A transport listener must be set before connection attempts.");
- }
-
- if (host == null || host.isEmpty()) {
- throw new IllegalArgumentException("Transport host value cannot be null");
- }
-
- if (port < 0 && options.defaultTcpPort() < 0 && (sslOptions.sslEnabled() && sslOptions.defaultSslPort() < 0)) {
- throw new IllegalArgumentException("Transport port value must be a non-negative int value or a default port configured");
- }
-
- this.host = host;
- this.listener = listener;
-
- if (port > 0) {
- this.port = port;
- } else {
- if (sslOptions.sslEnabled()) {
- this.port = sslOptions.defaultSslPort();
- } else {
- this.port = options.defaultTcpPort();
- }
- }
-
- bootstrap.handler(new ChannelInitializer<>() {
- @Override
- public void initChannel(Channel transportChannel) throws Exception {
- channel = transportChannel;
- nettyAllocator = new Netty5ProtonBufferAllocator(channel.bufferAllocator());
-
- configureChannel(transportChannel);
- try {
- listener.transportInitialized(TcpTransport.this);
- } catch (Throwable initError) {
- LOG.warn("Error during initialization of channel from Transport Listener");
- handleTransportFailure(transportChannel, IOExceptionSupport.create(initError));
- throw initError;
- }
- }
- });
-
- configureNetty(bootstrap, options);
-
- bootstrap.connect(getHost(), getPort()).addListener(new FutureListener<Channel>() {
-
- @Override
- public void operationComplete(Future<? extends Channel> future) throws Exception {
- if (future.isFailed()) {
- bootstrap.config().group().execute(() -> handleTransportFailure(channel, future.cause()));
- }
- }
- });
-
- return this;
- }
-
- @Override
- public void awaitConnect() throws InterruptedException, IOException {
- connectedLatch.await();
- if (!connected.get()) {
- if (failureCause != null) {
- throw failureCause;
- } else {
- throw new IOException("Transport was closed before a connection was established.");
- }
- }
- }
-
- @Override
- public boolean isConnected() {
- return connected.get();
- }
-
- @Override
- public boolean isSecure() {
- return sslOptions.sslEnabled();
- }
-
- @Override
- public String getHost() {
- return host;
- }
-
- @Override
- public int getPort() {
- return port;
- }
-
- @Override
- public void close() throws IOException {
- if (closed.compareAndSet(false, true)) {
- connected.set(false);
- connectedLatch.countDown();
- if (channel != null) {
- try {
- channel.close().asStage().await();
- } catch (InterruptedException e) {
- Thread.interrupted();
- }
- }
- }
- }
-
- @Override
- public ProtonBufferAllocator getBufferAllocator() {
- return nettyAllocator;
- }
-
- @Override
- public TcpTransport write(ProtonBuffer output) throws IOException {
- return write(output, null);
- }
-
- @Override
- public TcpTransport write(ProtonBuffer output, Runnable onComplete) throws IOException {
- checkConnected(output);
- LOG.trace("Attempted write of buffer: {}", output);
- return writeOutputBuffer(output, false, onComplete);
- }
-
- @Override
- public TcpTransport writeAndFlush(ProtonBuffer output) throws IOException {
- return writeAndFlush(output, null);
- }
-
- @Override
- public TcpTransport writeAndFlush(ProtonBuffer output, Runnable onComplete) throws IOException {
- checkConnected(output);
- LOG.trace("Attempted write and flush of buffer: {}", output);
- return writeOutputBuffer(output, true, onComplete);
- }
-
- @Override
- public TcpTransport flush() throws IOException {
- checkConnected();
- LOG.trace("Attempted flush of pending writes");
- channel.flush();
- return this;
- }
-
- @Override
- public TransportListener getTransportListener() {
- return listener;
- }
-
- @Override
- public TransportOptions getTransportOptions() {
- return options.clone();
- }
-
- @Override
- public SslOptions getSslOptions() {
- return sslOptions.clone();
- }
-
- @Override
- public Principal getLocalPrincipal() {
- Principal result = null;
-
- if (isSecure()) {
- SslHandler sslHandler = channel.pipeline().get(SslHandler.class);
- result = sslHandler.engine().getSession().getLocalPrincipal();
- }
-
- return result;
- }
-
- private TcpTransport writeOutputBuffer(final ProtonBuffer buffer, boolean flush, Runnable onComplete) {
- int writeCount = buffer.componentCount();
- Future<Void> writeFuture = null;
-
- try (ProtonBuffer ioBuffer = buffer; ProtonBufferComponentAccessor accessor = buffer.componentAccessor()) {
- for (ProtonBufferComponent output = accessor.firstReadable(); output != null; output = accessor.nextReadable()) {
- final Buffer nettyBuf;
-
- if (output instanceof Netty5ToProtonBufferAdapter) {
- nettyBuf = ((Netty5ToProtonBufferAdapter)output).unwrapAndRelease();
- } else if (output.unwrap() instanceof Buffer) {
- nettyBuf = ((Buffer) output.unwrap()).copy(true);
- } else {
- nettyBuf = channel.bufferAllocator().allocate(output.getReadableBytes());
- if (output.hasReadbleArray()) {
- nettyBuf.writeBytes(output.getReadableArray(), output.getReadableArrayOffset(), output.getReadableBytes());
- } else {
- nettyBuf.writeBytes(output.getReadableBuffer());
- }
- }
-
- if (--writeCount == 0 && flush) {
- writeFuture = channel.writeAndFlush(nettyBuf);
- } else {
- writeFuture = channel.write(nettyBuf);
- }
- }
-
- if (onComplete != null) {
- writeFuture.addListener(onComplete, TcpTransport::handleWriteComplete);
- }
- }
-
- return this;
- }
-
- @SuppressWarnings("unused")
- private TcpTransport writeOutputBufferAsWrappedNettyBuffer(final ProtonBuffer buffer, boolean flush, Runnable onComplete) {
- Future<Void> writeFuture = null;
-
- final Buffer nettyBuf = new ProtonBufferToNetty5Adapter(buffer.transfer());
-
- if (flush) {
- writeFuture = channel.writeAndFlush(nettyBuf);
- } else {
- writeFuture = channel.write(nettyBuf);
- }
-
- if (onComplete != null) {
- writeFuture.addListener(onComplete, TcpTransport::handleWriteComplete);
- }
-
- return this;
- }
-
- private static void handleWriteComplete(Runnable onComplete, Future<? extends Void> future) {
- if (future.isSuccess()) {
- onComplete.run();
- }
- }
-
- //----- Internal implementation details, can be overridden as needed -----//
-
- protected void addAdditionalHandlers(ChannelPipeline pipeline) {
-
- }
-
- protected ChannelHandler createChannelHandler() {
- return new NettyTcpTransportHandler();
- }
-
- //----- Event Handlers which can be overridden in subclasses -------------//
-
- protected void handleConnected(Channel connectedChannel) throws Exception {
- LOG.trace("Channel has become active! Channel is {}", connectedChannel);
- channel = connectedChannel;
- connected.set(true);
- listener.transportConnected(this);
- connectedLatch.countDown();
- }
-
- protected void handleTransportFailure(Channel failedChannel, Throwable cause) {
- if (!closed.get()) {
- LOG.trace("Transport indicates connection failure! Channel is {}", failedChannel);
- failureCause = IOExceptionSupport.create(cause);
- channel = failedChannel;
- connected.set(false);
- connectedLatch.countDown();
-
- LOG.trace("Firing onTransportError listener");
- if (channel.executor().inEventLoop()) {
- listener.transportError(failureCause);
- } else {
- channel.executor().execute(() -> {
- listener.transportError(failureCause);
- });
- }
- } else {
- LOG.trace("Closed Transport signalled that the channel ended: {}", channel);
- }
- }
-
- //----- State change handlers and checks ---------------------------------//
-
- protected final void checkConnected() throws IOException {
- if (!connected.get() || !channel.isActive()) {
- throw new IOException("Cannot send to a non-connected transport.", failureCause);
- }
- }
-
- private void checkConnected(ProtonBuffer output) throws IOException {
- if (!connected.get() || !channel.isActive()) {
- output.close();
- throw new IOException("Cannot send to a non-connected transport.", failureCause);
- }
- }
-
- private void configureNetty(Bootstrap bootstrap, TransportOptions options) {
- bootstrap.option(ChannelOption.TCP_NODELAY, options.tcpNoDelay());
- bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, options.connectTimeout());
- bootstrap.option(ChannelOption.SO_KEEPALIVE, options.tcpKeepAlive());
- bootstrap.option(ChannelOption.SO_LINGER, options.soLinger());
-
- if (options.sendBufferSize() != -1) {
- bootstrap.option(ChannelOption.SO_SNDBUF, options.sendBufferSize());
- }
-
- if (options.receiveBufferSize() != -1) {
- bootstrap.option(ChannelOption.SO_RCVBUF, options.receiveBufferSize());
- }
-
- if (options.trafficClass() != -1) {
- bootstrap.option(ChannelOption.IP_TOS, options.trafficClass());
- }
-
- if (options.localAddress() != null || options.localPort() != 0) {
- if (options.localAddress() != null) {
- bootstrap.localAddress(options.localAddress(), options.localPort());
- } else {
- bootstrap.localAddress(options.localPort());
- }
- }
- }
-
- private void configureChannel(final Channel channel) throws Exception {
- if (isSecure()) {
- final SslHandler sslHandler;
- try {
- sslHandler = SslSupport.createSslHandler(channel.bufferAllocator(), host, port, sslOptions);
- } catch (Exception ex) {
- LOG.warn("Error during initialization of channel from SSL Handler creation:");
- handleTransportFailure(channel, IOExceptionSupport.create(ex));
- throw IOExceptionSupport.create(ex);
- }
-
- channel.pipeline().addLast("ssl", sslHandler);
- }
-
- if (options.traceBytes()) {
- channel.pipeline().addLast("logger", new LoggingHandler(getClass()));
- }
-
- addAdditionalHandlers(channel.pipeline());
-
- channel.pipeline().addLast(createChannelHandler());
- }
-
- //----- Default implementation of Netty handler --------------------------//
-
- protected abstract class NettyDefaultHandler<E> extends SimpleChannelInboundHandler<E> {
-
- public NettyDefaultHandler() {
- super(false); // We will release buffer references manually.
- }
-
- @Override
- public final void channelRegistered(ChannelHandlerContext context) throws Exception {
- channel = context.channel();
- }
-
- @Override
- public void channelActive(ChannelHandlerContext context) throws Exception {
- // In the Secure case we need to let the handshake complete before we
- // trigger the connected event.
- if (!isSecure()) {
- handleConnected(context.channel());
- } else {
- SslHandler sslHandler = context.pipeline().get(SslHandler.class);
- sslHandler.handshakeFuture().addListener(new FutureListener<Channel>() {
- @Override
- public void operationComplete(Future<? extends Channel> future) throws Exception {
- if (future.isSuccess()) {
- LOG.trace("SSL Handshake has completed: {}", channel);
- handleConnected(channel);
- } else {
- LOG.trace("SSL Handshake has failed: {}", channel);
- handleTransportFailure(channel, future.cause());
- }
- }
- });
- }
- }
-
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- ctx.flush();
- }
-
- @Override
- public void channelInactive(ChannelHandlerContext context) throws Exception {
- handleTransportFailure(context.channel(), new IOException("Remote closed connection unexpectedly"));
- }
-
- @Override
- public void channelExceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
- handleTransportFailure(context.channel(), cause);
- }
-
- protected void dispatchReadBuffer(Buffer buffer) throws Exception {
- LOG.trace("New data read: {}", buffer);
-
- // Wrap the buffer and make it read-only as the handlers should not be altering the
- // read bytes and if they need to they should be copying them. If the handler doesn't
- // take ownership of the incoming buffer then we will close it and the reference count
- // will be decremented here (default auto decrement has been disabled).
- final ProtonBuffer wrapped = nettyAllocator.wrap(buffer).convertToReadOnly();
-
- try (wrapped) {
- listener.transportRead(wrapped);
- }
- }
- }
-
- //----- Handle binary data over socket connections -----------------------//
-
- protected class NettyTcpTransportHandler extends NettyDefaultHandler<Buffer> {
-
- @Override
- protected void messageReceived(ChannelHandlerContext ctx, Buffer buffer) throws Exception {
- dispatchReadBuffer(buffer);
- }
- }
-
- @Override
- public URI getRemoteURI() {
- if (host != null) {
- try {
- return new URI(getScheme(), null, host, port, null, null, null);
- } catch (URISyntaxException e) {
- }
- }
-
- return null;
- }
-
- protected String getScheme() {
- return isSecure() ? "ssl" : "tcp";
- }
-}
diff --git a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/WebSocketTransport.java b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/WebSocketTransport.java
deleted file mode 100644
index 62c0097d..00000000
--- a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/transport/netty5/WebSocketTransport.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.bootstrap.Bootstrap;
-import io.netty5.buffer.Buffer;
-import io.netty5.channel.Channel;
-import io.netty5.channel.ChannelHandler;
-import io.netty5.channel.ChannelHandlerAdapter;
-import io.netty5.channel.ChannelHandlerContext;
-import io.netty5.channel.ChannelPipeline;
-import io.netty5.handler.codec.http.DefaultHttpContent;
-import io.netty5.handler.codec.http.FullHttpResponse;
-import io.netty5.handler.codec.http.HttpClientCodec;
-import io.netty5.handler.codec.http.HttpObjectAggregator;
-import io.netty5.handler.codec.http.headers.HttpHeaders;
-import io.netty5.handler.codec.http.websocketx.BinaryWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.CloseWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.ContinuationWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.PingWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.PongWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.TextWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketClientHandshaker;
-import io.netty5.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
-import io.netty5.handler.codec.http.websocketx.WebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketVersion;
-import io.netty5.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
-import io.netty5.util.concurrent.Future;
-import io.netty5.util.concurrent.FutureListener;
-
-/**
- * Netty based WebSockets Transport that wraps and extends the TCP Transport.
- */
-public class WebSocketTransport extends TcpTransport {
-
- private static final Logger LOG = LoggerFactory.getLogger(WebSocketTransport.class);
-
- private static final String AMQP_SUB_PROTOCOL = "amqp";
-
- private Future<Void> handshakeTimeoutFuture;
-
- /**
- * Create a new {@link WebSocketTransport} instance with the given configuration.
- *
- * @param bootstrap
- * the {@link Bootstrap} that this transport's IO is bound to.
- * @param options
- * the {@link TransportOptions} used to configure the socket connection.
- * @param sslOptions
- * the {@link SslOptions} to use if the options indicate SSL is enabled.
- */
- public WebSocketTransport(Bootstrap bootstrap, TransportOptions options, SslOptions sslOptions) {
- super(bootstrap, options, sslOptions);
- }
-
- @Override
- public URI getRemoteURI() {
- if (host != null) {
- try {
- return new URI(getScheme(), null, host, port, options.webSocketPath(), null, null);
- } catch (URISyntaxException e) {
- }
- }
-
- return null;
- }
-
- @Override
- protected ChannelHandler createChannelHandler() {
- return new NettyWebSocketTransportHandler();
- }
-
- @Override
- protected void addAdditionalHandlers(ChannelPipeline pipeline) {
- pipeline.addLast(new HttpClientCodec());
- pipeline.addLast(new HttpObjectAggregator<DefaultHttpContent>(8192));
- if (options.webSocketCompression()) {
- pipeline.addLast(WebSocketClientCompressionHandler.INSTANCE);
- }
- }
-
- @Override
- protected void handleConnected(Channel channel) throws Exception {
- LOG.trace("Channel has become active, awaiting WebSocket handshake! Channel is {}", channel);
- }
-
- @Override
- protected String getScheme() {
- return isSecure() ? "wss" : "ws";
- }
-
- //----- Handle connection events -----------------------------------------//
-
- private class OutputBufferToBinaryFrameHandler extends ChannelHandlerAdapter {
-
- @Override
- public Future<Void> write(ChannelHandlerContext ctx, Object msg) {
- return ctx.write(new BinaryWebSocketFrame((Buffer) msg));
- }
- }
-
- private class NettyWebSocketTransportHandler extends NettyDefaultHandler<Object> implements ChannelHandler {
-
- private final WebSocketClientHandshaker handshaker;
-
- public NettyWebSocketTransportHandler() {
- HttpHeaders headers = HttpHeaders.newHeaders();
-
- options.webSocketHeaders().forEach((key, value) -> {
- headers.set(key, value);
- });
-
- handshaker = WebSocketClientHandshakerFactory.newHandshaker(
- getRemoteURI(), WebSocketVersion.V13, AMQP_SUB_PROTOCOL,
- true, headers, options.webSocketMaxFrameSize());
- }
-
- @Override
- public void channelInactive(ChannelHandlerContext context) throws Exception {
- if (handshakeTimeoutFuture != null) {
- handshakeTimeoutFuture.cancel();
- }
-
- super.channelInactive(context);
- }
-
- @Override
- public void channelActive(ChannelHandlerContext context) throws Exception {
- handshaker.handshake(context.channel()).addListener(new FutureListener<Void>() {
-
- @Override
- public void operationComplete(Future<? extends Void> future) throws Exception {
- if (future.isSuccess()) {
- // Now we can add a transformer for outbound buffers that will produce
- // binary websocket frame wrappers to ensure our writes are encoded.
- context.pipeline().addLast(new OutputBufferToBinaryFrameHandler());
- }
- }
- });
-
- handshakeTimeoutFuture = context.executor().schedule(()-> {
- LOG.trace("WebSocket handshake timed out! Channel is {}", context.channel());
- if (!handshaker.isHandshakeComplete()) {
- WebSocketTransport.super.handleTransportFailure(channel, new IOException("WebSocket handshake timed out"));
- }
- }, getTransportOptions().connectTimeout(), TimeUnit.MILLISECONDS);
-
- super.channelActive(context);
- }
-
- @Override
- protected void messageReceived(ChannelHandlerContext ctx, Object message) throws Exception {
- LOG.trace("New data read: incoming: {}", message);
-
- Channel ch = ctx.channel();
- if (!handshaker.isHandshakeComplete()) {
- handshaker.finishHandshake(ch, (FullHttpResponse) message);
- LOG.trace("WebSocket Client connected! {}", ctx.channel());
- // Now trigger super processing as we are really connected.
- if (handshakeTimeoutFuture.cancel()) {
- WebSocketTransport.super.handleConnected(ch);
- }
-
- return;
- }
-
- // We shouldn't get this since we handle the handshake previously.
- if (message instanceof FullHttpResponse) {
- FullHttpResponse response = (FullHttpResponse) message;
- throw new IllegalStateException(
- "Unexpected FullHttpResponse (getStatus=" + response.status() +
- ", content=" + response.payload().toString(StandardCharsets.UTF_8) + ')');
- }
-
- WebSocketFrame frame = (WebSocketFrame) message;
- if (frame instanceof TextWebSocketFrame) {
- TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
- LOG.warn("WebSocket Client received message: {}", textFrame.text());
- ctx.fireChannelExceptionCaught(new IOException("Received invalid frame over WebSocket."));
- } else if (frame instanceof BinaryWebSocketFrame) {
- BinaryWebSocketFrame binaryFrame = (BinaryWebSocketFrame) frame;
- LOG.trace("WebSocket Client received data: {} bytes", binaryFrame.binaryData().readableBytes());
- dispatchReadBuffer(binaryFrame.binaryData());
- } else if (frame instanceof ContinuationWebSocketFrame) {
- ContinuationWebSocketFrame continuationFrame = (ContinuationWebSocketFrame) frame;
- LOG.trace("WebSocket Client received data continuation: {} bytes", continuationFrame.binaryData().readableBytes());
- dispatchReadBuffer(continuationFrame.binaryData());
- } else if (frame instanceof PingWebSocketFrame) {
- LOG.trace("WebSocket Client received ping, response with pong");
- ch.write(new PongWebSocketFrame(frame.binaryData()));
- } else if (frame instanceof CloseWebSocketFrame) {
- LOG.trace("WebSocket Client received closing");
- ch.close();
- }
- }
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ReconnectStreamReceiverTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ReconnectStreamReceiverTest.java
index 13173783..bc5c3214 100644
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ReconnectStreamReceiverTest.java
+++ b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ReconnectStreamReceiverTest.java
@@ -105,7 +105,6 @@ class ReconnectStreamReceiverTest extends ImperativeClientTestCase {
}
}
- @SuppressWarnings("resource")
@Test
public void testCannotReceiveFromStreamStartedBeforeReconnection() throws Exception {
final byte[] payload = createEncodedMessage(new AmqpValue<>("Hello World"));
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java
index 93c5c395..305dbe0c 100644
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java
+++ b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/SslConnectionTest.java
@@ -39,7 +39,7 @@ import org.apache.qpid.protonj2.client.Connection;
import org.apache.qpid.protonj2.client.ConnectionOptions;
import org.apache.qpid.protonj2.client.SslOptions;
import org.apache.qpid.protonj2.client.test.ImperativeClientTestCase;
-import org.apache.qpid.protonj2.client.transport.netty5.SslSupport;
+import org.apache.qpid.protonj2.client.transport.netty4.SslSupport;
import org.apache.qpid.protonj2.test.driver.ProtonTestServer;
import org.apache.qpid.protonj2.test.driver.ProtonTestServerOptions;
import org.apache.qpid.protonj2.types.security.SaslCode;
@@ -50,7 +50,7 @@ import org.junit.jupiter.api.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.netty5.handler.ssl.OpenSsl;
+import io.netty.handler.ssl.OpenSsl;
/**
* Test for the Connection class
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyBlackHoleServer.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyBlackHoleServer.java
deleted file mode 100644
index 67b5d72d..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyBlackHoleServer.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.channel.ChannelHandler;
-import io.netty5.channel.ChannelHandlerAdapter;
-import io.netty5.channel.ChannelHandlerContext;
-
-public class NettyBlackHoleServer extends NettyServer {
-
- private static final Logger LOG = LoggerFactory.getLogger(NettyBlackHoleServer.class);
-
- public NettyBlackHoleServer(TransportOptions options, SslOptions sslOptions) {
- super(options, sslOptions);
- }
-
- public NettyBlackHoleServer(TransportOptions options, SslOptions sslOptions, boolean needClientAuth) {
- super(options, sslOptions, needClientAuth);
- }
-
- @Override
- protected ChannelHandler getServerHandler() {
- return new BlackHoleInboundHandler();
- }
-
- private class BlackHoleInboundHandler extends ChannelHandlerAdapter {
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) {
- LOG.trace("BlackHoleInboundHandler: Channel read, dropping: {}", msg);
- }
- }
-}
\ No newline at end of file
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyEchoServer.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyEchoServer.java
deleted file mode 100644
index ba86b7da..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyEchoServer.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.buffer.Buffer;
-import io.netty5.channel.ChannelHandler;
-import io.netty5.channel.ChannelHandlerContext;
-import io.netty5.channel.SimpleChannelInboundHandler;
-
-/**
- * Simple Netty Server used to echo all data.
- */
-public class NettyEchoServer extends NettyServer {
-
- private static final Logger LOG = LoggerFactory.getLogger(NettyEchoServer.class);
-
- public NettyEchoServer(TransportOptions options, SslOptions sslOptions, boolean needClientAuth) {
- super(options, sslOptions, needClientAuth);
- }
-
- @Override
- protected ChannelHandler getServerHandler() {
- return new EchoServerHandler();
- }
-
- private class EchoServerHandler extends SimpleChannelInboundHandler<Buffer> {
-
- @Override
- public void messageReceived(ChannelHandlerContext ctx, Buffer msg) {
- LOG.trace("Channel read: {}", msg);
- ctx.write(msg.copy());
- }
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyIOContextTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyIOContextTest.java
deleted file mode 100644
index 1affaeb6..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyIOContextTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.junit.jupiter.api.Test;
-
-class NettyIOContextTest {
-
- @Test
- void testCannotCreateNewTransportFromShutdownBootStrap() {
- Netty5IOContext context = new Netty5IOContext(new TransportOptions(), new SslOptions(), "test");
-
- context.shutdown();
-
- assertThrows(IllegalStateException.class, () -> context.newTransport());
- }
-
- @Test
- void testEventLoopGroupAccessibleAfterCreate() {
- Netty5IOContext context = new Netty5IOContext(new TransportOptions(), new SslOptions(), "test");
-
- assertNotNull(context.ioScheduler());
- assertFalse(context.ioScheduler().isShutdown());
-
- context.shutdown();
-
- assertTrue(context.ioScheduler().isShutdown());
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyServer.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyServer.java
deleted file mode 100644
index ce3a75be..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/NettyServer.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.nio.charset.StandardCharsets;
-import java.util.Set;
-import java.util.concurrent.ConcurrentSkipListSet;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.bootstrap.ServerBootstrap;
-import io.netty5.buffer.Buffer;
-import io.netty5.buffer.BufferAllocator;
-import io.netty5.buffer.DefaultBufferAllocators;
-import io.netty5.channel.Channel;
-import io.netty5.channel.ChannelHandler;
-import io.netty5.channel.ChannelHandlerAdapter;
-import io.netty5.channel.ChannelHandlerContext;
-import io.netty5.channel.ChannelInitializer;
-import io.netty5.channel.ChannelOption;
-import io.netty5.channel.EventLoopGroup;
-import io.netty5.channel.MultithreadEventLoopGroup;
-import io.netty5.channel.nio.NioHandler;
-import io.netty5.channel.socket.nio.NioServerSocketChannel;
-import io.netty5.handler.codec.http.DefaultFullHttpResponse;
-import io.netty5.handler.codec.http.DefaultHttpContent;
-import io.netty5.handler.codec.http.FullHttpRequest;
-import io.netty5.handler.codec.http.FullHttpResponse;
-import io.netty5.handler.codec.http.HttpObjectAggregator;
-import io.netty5.handler.codec.http.HttpResponseStatus;
-import io.netty5.handler.codec.http.HttpServerCodec;
-import io.netty5.handler.codec.http.HttpUtil;
-import io.netty5.handler.codec.http.HttpVersion;
-import io.netty5.handler.codec.http.websocketx.BinaryWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.ContinuationWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketServerHandshakeCompletionEvent;
-import io.netty5.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
-import io.netty5.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
-import io.netty5.handler.logging.LogLevel;
-import io.netty5.handler.logging.LoggingHandler;
-import io.netty5.handler.ssl.SslHandler;
-import io.netty5.util.concurrent.Future;
-import io.netty5.util.concurrent.FutureListener;
-
-/**
- * Base Server implementation used to create Netty based server implementations for
- * unit testing aspects of the client code.
- */
-public abstract class NettyServer implements AutoCloseable {
-
- private static final Logger LOG = LoggerFactory.getLogger(NettyServer.class);
-
- static final String WEBSOCKET_PATH = "/";
- static final int SERVER_CHOOSES_PORT = 0;
-
- private EventLoopGroup bossGroup;
- private EventLoopGroup workerGroup;
- private Channel serverChannel;
- private final TransportOptions options;
- private final SslOptions sslOptions;
- private int serverPort = SERVER_CHOOSES_PORT;
- private final boolean needClientAuth;
- private int maxFrameSize = TransportOptions.DEFAULT_WEBSOCKET_MAX_FRAME_SIZE;
- private String webSocketPath = WEBSOCKET_PATH;
- private volatile boolean fragmentWrites;
- private volatile SslHandler sslHandler;
- private volatile WebSocketServerHandshakeCompletionEvent handshakeComplete;
- private final CountDownLatch handshakeCompletion = new CountDownLatch(1);
-
- private final AtomicBoolean started = new AtomicBoolean();
-
- public NettyServer(TransportOptions options, SslOptions sslOptions) {
- this(options, sslOptions, false);
- }
-
- public NettyServer(TransportOptions options, SslOptions sslOptions, boolean needClientAuth) {
- this.sslOptions = sslOptions;
- this.options = options;
- this.needClientAuth = needClientAuth;
- }
-
- public boolean isSecureServer() {
- return sslOptions.sslEnabled();
- }
-
- public boolean isWebSocketServer() {
- return options.useWebSockets();
- }
-
- public boolean isUseWebSocketCompression() {
- return options.webSocketCompression();
- }
-
- public String getWebSocketPath() {
- return webSocketPath;
- }
-
- public void setWebSocketPath(String webSocketPath) {
- this.webSocketPath = webSocketPath;
- }
-
- public int getMaxFrameSize() {
- return maxFrameSize;
- }
-
- public void setMaxFrameSize(int maxFrameSize) {
- this.maxFrameSize = maxFrameSize;
- }
-
- public void setFragmentWrites(boolean fragmentWrites) {
- if(!isWebSocketServer()) {
- throw new IllegalStateException("Only applicable to WebSocket servers");
- }
-
- this.fragmentWrites = fragmentWrites;
- }
-
- public boolean isFragmentWrites() {
- return fragmentWrites;
- }
-
- public boolean awaitHandshakeCompletion(long delayMs) throws InterruptedException {
- return handshakeCompletion.await(delayMs, TimeUnit.MILLISECONDS);
- }
-
- public WebSocketServerHandshakeCompletionEvent getHandshakeComplete() {
- return handshakeComplete;
- }
-
- protected URI getConnectionURI() throws Exception {
- if (!started.get()) {
- throw new IllegalStateException("Cannot get URI of non-started server");
- }
-
- int port = getServerPort();
-
- String scheme;
- String path;
-
- if (isWebSocketServer()) {
- if (isSecureServer()) {
- scheme = "amqpwss";
- } else {
- scheme = "amqpws";
- }
- } else {
- if (isSecureServer()) {
- scheme = "amqps";
- } else {
- scheme = "amqp";
- }
- }
-
- if (isWebSocketServer()) {
- path = getWebSocketPath();
- } else {
- path = null;
- }
-
- return new URI(scheme, null, "localhost", port, path, null, null);
- }
-
- public void start() throws Exception {
- start(serverPort);
- }
-
- public void start(int listenOn) throws Exception {
- if (started.compareAndSet(false, true)) {
-
- // Configure the server.
- bossGroup = new MultithreadEventLoopGroup(1, NioHandler.newFactory());
- workerGroup = new MultithreadEventLoopGroup(NioHandler.newFactory());
-
- ServerBootstrap server = new ServerBootstrap();
- server.group(bossGroup, workerGroup);
- server.channel(NioServerSocketChannel.class);
- server.option(ChannelOption.SO_BACKLOG, 100);
- server.handler(new LoggingHandler(LogLevel.INFO));
- server.childHandler(new ChannelInitializer<>() {
-
- @Override
- public void initChannel(Channel ch) throws Exception {
- if (isSecureServer()) {
- SSLContext context = SslSupport.createJdkSslContext(sslOptions);
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, sslOptions);
- engine.setUseClientMode(false);
- engine.setNeedClientAuth(needClientAuth);
- sslHandler = new SslHandler(engine);
- ch.pipeline().addLast(sslHandler);
- }
-
- if (options.traceBytes()) {
- ch.pipeline().addLast("logger", new LoggingHandler(getClass()));
- }
-
- if (isWebSocketServer()) {
- ch.pipeline().addLast(new HttpServerCodec());
- ch.pipeline().addLast(new HttpObjectAggregator<DefaultHttpContent>(65536));
- if (isUseWebSocketCompression()) {
- ch.pipeline().addLast(new WebSocketServerCompressionHandler());
- }
- ch.pipeline().addLast(new WebSocketServerProtocolHandler(getWebSocketPath(), "amqp", true, maxFrameSize));
- }
-
- ch.pipeline().addLast(new NettyServerOutboundHandler());
- ch.pipeline().addLast(new NettyServerInboundHandler());
- ch.pipeline().addLast(getServerHandler());
- }
- });
-
- // Start the server.
- serverChannel = server.bind(getServerPort()).asStage().get();
- serverPort = ((InetSocketAddress) serverChannel.localAddress()).getPort();
- }
- }
-
- protected abstract ChannelHandler getServerHandler();
-
- public void stop() throws InterruptedException {
- if (started.compareAndSet(true, false)) {
- try {
- LOG.info("Sync on server channel close");
- serverChannel.close().asStage().await();
- } catch (InterruptedException e) {
- }
-
- for (Channel channel : clients) {
- try {
- channel.close().asStage().await();
- } catch (Exception ex) {}
- }
-
- clients.clear();
-
- // Shut down all event loops to terminate all threads.
- LOG.trace("Shutting down boss group");
- bossGroup.shutdownGracefully(0, 2, TimeUnit.MILLISECONDS);
- bossGroup.awaitTermination(3, TimeUnit.MILLISECONDS);
- LOG.trace("Boss group shut down");
-
- LOG.trace("Shutting down worker group");
- workerGroup.shutdownGracefully(0, 2, TimeUnit.MILLISECONDS);
- workerGroup.awaitTermination(3, TimeUnit.MILLISECONDS);
- LOG.trace("Worker group shut down");
- }
- }
-
- @Override
- public void close() throws InterruptedException {
- stop();
- }
-
- public int getServerPort() {
- if (!started.get()) {
- throw new IllegalStateException("Cannot get server port of non-started server");
- }
-
- return serverPort;
- }
-
- public int getClientCount() {
- return clients.size();
- }
-
- private class NettyServerOutboundHandler extends ChannelHandlerAdapter {
-
- @Override
- public Future<Void> write(ChannelHandlerContext ctx, Object msg) {
- LOG.trace("NettyServerHandler: Channel write: {}", msg);
- if (isWebSocketServer() && msg instanceof Buffer) {
- if (isFragmentWrites()) {
- Buffer orig = (Buffer) msg;
- int origIndex = orig.readerOffset();
- int split = orig.readableBytes()/2;
-
- Buffer part1 = orig.copy(origIndex, split);
- LOG.trace("NettyServerHandler: Part1: {}", part1);
- orig.readerOffset(origIndex + split);
- LOG.trace("NettyServerHandler: Part2: {}", orig);
-
- BinaryWebSocketFrame frame1 = new BinaryWebSocketFrame(false, 0, part1);
- ctx.writeAndFlush(frame1);
- ContinuationWebSocketFrame frame2 = new ContinuationWebSocketFrame(true, 0, orig);
- return ctx.write(frame2);
- } else {
- BinaryWebSocketFrame frame = new BinaryWebSocketFrame((Buffer) msg);
- return ctx.write(frame);
- }
- } else {
- return ctx.write(msg);
- }
- }
- }
-
- private static final Set<Channel> clients = new ConcurrentSkipListSet<>();
-
- private class NettyServerInboundHandler extends ChannelHandlerAdapter {
-
- @Override
- public void channelInboundEvent(ChannelHandlerContext context, Object payload) {
- if (payload instanceof WebSocketServerHandshakeCompletionEvent) {
- handshakeComplete = (WebSocketServerHandshakeCompletionEvent) payload;
- handshakeCompletion.countDown();
- }
- }
-
- @Override
- public void channelActive(final ChannelHandlerContext ctx) {
- LOG.info("NettyServerHandler -> New active channel: {}", ctx.channel());
- SslHandler handler = ctx.pipeline().get(SslHandler.class);
- if (handler != null) {
- handler.handshakeFuture().addListener(new FutureListener<Channel>() {
- @Override
- public void operationComplete(Future<? extends Channel> future) throws Exception {
- LOG.info("Server -> SSL handshake completed. Succeeded: {}", future.isSuccess());
- if (!future.isSuccess()) {
- ctx.close();
- }
- }
- });
- }
-
- clients.add(ctx.channel());
- }
-
- @Override
- public void channelInactive(ChannelHandlerContext ctx) throws Exception {
- LOG.info("NettyServerHandler: channel has gone inactive: {}", ctx.channel());
- ctx.close();
- clients.remove(ctx.channel());
- }
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) {
- LOG.trace("NettyServerHandler: Channel read: {}", msg);
- if (msg instanceof WebSocketFrame) {
- WebSocketFrame frame = (WebSocketFrame) msg;
- ctx.fireChannelRead(frame.binaryData());
- } else if (msg instanceof FullHttpRequest) {
- // Reject anything not on the WebSocket path
- FullHttpRequest request = (FullHttpRequest) msg;
- sendHttpResponse(ctx, request,
- new DefaultFullHttpResponse(
- HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST, DefaultBufferAllocators.onHeapAllocator().allocate(0)));
- } else {
- // Forward anything else along to the next handler.
- ctx.fireChannelRead(msg);
- }
- }
-
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) {
- ctx.flush();
- }
-
- @Override
- public void channelExceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
- LOG.info("NettyServerHandler: NettyServerHandlerException caught on channel: {}", ctx.channel());
- // Close the connection when an exception is raised.
- cause.printStackTrace();
- ctx.close();
- }
- }
-
- private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response) {
- // Generate an error page if response getStatus code is not OK (200).
- if (response.status().code() != 200) {
- try (Buffer buf = BufferAllocator.onHeapUnpooled().copyOf(response.status().toString().getBytes(StandardCharsets.UTF_8))) {
- response.payload().writeBytes(buf);
- HttpUtil.setContentLength(response, response.payload().readableBytes());
- }
- }
-
- // Send the response and close the connection if necessary.
- Future<Void> f = ctx.channel().writeAndFlush(response);
- if (!HttpUtil.isKeepAlive(request) || response.status().code() != 200) {
- f.addListener((channel) -> ctx.channel().close());
- }
- }
-
- protected SslHandler getSslHandler() {
- return sslHandler;
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/OpenSslTransportTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/OpenSslTransportTest.java
deleted file mode 100644
index 0d4c7ae3..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/OpenSslTransportTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
-
-import java.lang.reflect.Field;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.transport.Transport;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.Timeout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.channel.Channel;
-import io.netty5.channel.ChannelHandler;
-import io.netty5.handler.ssl.OpenSsl;
-import io.netty5.handler.ssl.OpenSslEngine;
-import io.netty5.handler.ssl.SslHandler;
-
-/**
- * Test basic functionality of the Netty based TCP Transport running in secure mode (SSL).
- */
-@Timeout(30)
-public class OpenSslTransportTest extends SslTransportTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(OpenSslTransportTest.class);
-
- @Test
- public void testConnectToServerWithOpenSSLEnabled() throws Exception {
- doTestOpenSSLSupport(true);
- }
-
- @Test
- public void testConnectToServerWithOpenSSLDisabled() throws Exception {
- doTestOpenSSLSupport(false);
- }
-
- private void doTestOpenSSLSupport(boolean useOpenSSL) throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- SslOptions options = createSSLOptions();
- options.allowNativeSSL(useOpenSSL);
-
- Transport transport = createTransport(createTransportOptions(), options);
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost());
- assertEquals(port, transport.getPort());
- assertOpenSSL("Transport should be using OpenSSL", useOpenSSL, transport);
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testConnectToServerWithUserSuppliedSSLContextWorksWhenOpenSSLRequested() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- SslOptions options = new SslOptions();
-
- options.sslEnabled(true);
- options.keyStoreLocation(CLIENT_KEYSTORE);
- options.keyStorePassword(PASSWORD);
- options.trustStoreLocation(CLIENT_TRUSTSTORE);
- options.trustStorePassword(PASSWORD);
- options.storeType(KEYSTORE_TYPE);
-
- SSLContext sslContext = SslSupport.createJdkSslContext(options);
-
- options = new SslOptions();
- options.sslEnabled(true);
- options.verifyHost(false);
- options.allowNativeSSL(true);
- options.sslContextOverride(sslContext);
-
- Transport transport = createTransport(createTransportOptions(), options);
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
- assertOpenSSL("Transport should not be using OpenSSL", false, transport);
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- private void assertOpenSSL(String message, boolean expected, Transport transport) throws Exception {
- Field channel = null;
- Class<?> transportType = transport.getClass();
-
- while (transportType != null && channel == null) {
- try {
- channel = transportType.getDeclaredField("channel");
- } catch (NoSuchFieldException error) {
- transportType = transportType.getSuperclass();
- if (Object.class.equals(transportType)) {
- transportType = null;
- }
- }
- }
-
- assertNotNull(channel, "Transport implementation unknown");
-
- channel.setAccessible(true);
-
- Channel activeChannel = (Channel) channel.get(transport) ;
- ChannelHandler handler = activeChannel.pipeline().get("ssl");
- assertNotNull(handler, "Channel should have an SSL Handler registered");
- assertTrue(handler instanceof SslHandler);
- SslHandler sslHandler = (SslHandler) handler;
-
- if (expected) {
- assertTrue(sslHandler.engine() instanceof OpenSslEngine, message);
- } else {
- assertFalse(sslHandler.engine() instanceof OpenSslEngine, message);
- }
- }
-
- @Override
- @Disabled("Can't apply keyAlias in Netty OpenSSL impl")
- @Test
- public void testConnectWithSpecificClientAuthKeyAlias1() throws Exception {
- // TODO - Revert to superclass version if keyAlias becomes supported for Netty.
- }
-
- @Override
- @Disabled("Can't apply keyAlias in Netty OpenSSL impl")
- @Test
- public void testConnectWithSpecificClientAuthKeyAlias2() throws Exception {
- // TODO - Revert to superclass version if keyAlias becomes supported for Netty.
- }
-
- @Override
- protected SslOptions createSSLOptionsIsVerify(boolean verifyHost) {
- SslOptions options = new SslOptions();
-
- options.sslEnabled(true);
- options.allowNativeSSL(true);
- options.keyStoreLocation(CLIENT_KEYSTORE);
- options.keyStorePassword(PASSWORD);
- options.trustStoreLocation(CLIENT_TRUSTSTORE);
- options.trustStorePassword(PASSWORD);
- options.storeType(KEYSTORE_TYPE);
- options.verifyHost(verifyHost);
-
- return options;
- }
-
- @Override
- protected SslOptions createSSLOptionsWithoutTrustStore(boolean trustAll) {
- SslOptions options = new SslOptions();
-
- options.sslEnabled(true);
- options.storeType(KEYSTORE_TYPE);
- options.allowNativeSSL(true);
- options.trustAll(trustAll);
-
- return options;
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SecureWebSocketTransportTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SecureWebSocketTransportTest.java
deleted file mode 100644
index 992679c8..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SecureWebSocketTransportTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.apache.qpid.protonj2.client.transport.Transport;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Test the WebSocketTransport with channel level security enabled.
- */
-public class SecureWebSocketTransportTest extends SslTransportTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(SecureWebSocketTransportTest.class);
-
- @Test
- public void testEnsureNettyIOContextCreatesWebSocketTransport() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
-
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- } catch (Exception e) {
- LOG.info("Failed to connect to: {}:{} as expected.", HOSTNAME, port);
- fail("Should not have failed to connect to the server: " + HOSTNAME + ":" + port);
- }
-
- assertTrue(transport instanceof WebSocketTransport);
- assertTrue(transport.isConnected());
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Override
- protected TransportOptions createTransportOptions() {
- return new TransportOptions().useWebSockets(true);
- }
-
- @Override
- protected TransportOptions createServerTransportOptions() {
- return new TransportOptions().useWebSockets(true);
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupportTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupportTest.java
deleted file mode 100644
index 5984ff3b..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslSupportTest.java
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
-
-import java.io.IOException;
-import java.security.UnrecoverableKeyException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.test.ImperativeClientTestCase;
-import org.junit.jupiter.api.Test;
-
-import io.netty5.buffer.BufferAllocator;
-import io.netty5.handler.ssl.OpenSsl;
-import io.netty5.handler.ssl.OpenSslEngine;
-import io.netty5.handler.ssl.SslContext;
-import io.netty5.handler.ssl.SslHandler;
-
-/**
- * Tests for the TransportSupport class.
- */
-@SuppressWarnings("deprecation")
-public class SslSupportTest extends ImperativeClientTestCase {
-
- public static final String PASSWORD = "password";
-
- public static final String HOSTNAME = "localhost";
-
- public static final String BROKER_JKS_KEYSTORE = "src/test/resources/broker-jks.keystore";
- public static final String BROKER_JKS_TRUSTSTORE = "src/test/resources/broker-jks.truststore";
- public static final String CLIENT_JKS_KEYSTORE = "src/test/resources/client-jks.keystore";
- public static final String CLIENT_JKS_TRUSTSTORE = "src/test/resources/client-jks.truststore";
-
- public static final String BROKER_JCEKS_KEYSTORE = "src/test/resources/broker-jceks.keystore";
- public static final String BROKER_JCEKS_TRUSTSTORE = "src/test/resources/broker-jceks.truststore";
- public static final String CLIENT_JCEKS_KEYSTORE = "src/test/resources/client-jceks.keystore";
- public static final String CLIENT_JCEKS_TRUSTSTORE = "src/test/resources/client-jceks.truststore";
-
- public static final String BROKER_PKCS12_KEYSTORE = "src/test/resources/broker-pkcs12.keystore";
- public static final String BROKER_PKCS12_TRUSTSTORE = "src/test/resources/broker-pkcs12.truststore";
- public static final String CLIENT_PKCS12_KEYSTORE = "src/test/resources/client-pkcs12.keystore";
- public static final String CLIENT_PKCS12_TRUSTSTORE = "src/test/resources/client-pkcs12.truststore";
-
- public static final String KEYSTORE_JKS_TYPE = "jks";
- public static final String KEYSTORE_JCEKS_TYPE = "jceks";
- public static final String KEYSTORE_PKCS12_TYPE = "pkcs12";
-
- public static final String[] ENABLED_PROTOCOLS = new String[] { "TLSv1" };
-
- // Currently the OpenSSL implementation cannot disable SSLv2Hello
- public static final String[] ENABLED_OPENSSL_PROTOCOLS = new String[] { "SSLv2Hello", "TLSv1" };
-
- private static final String ALIAS_DOES_NOT_EXIST = "alias.does.not.exist";
- private static final String ALIAS_CA_CERT = "ca";
-
- @Test
- public void testLegacySslProtocolsDisabledByDefaultJDK() throws Exception {
- SslOptions options = createJksSslOptions(null);
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.contains("SSLv3"), "SSLv3 should not be enabled by default");
- assertFalse(engineProtocols.contains("SSLv2Hello"), "SSLv2Hello should not be enabled by default");
- }
-
- @Test
- public void testLegacySslProtocolsDisabledByDefaultOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions(null);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.contains("SSLv3"), "SSLv3 should not be enabled by default");
-
- // TODO - Netty is currently unable to disable OpenSSL SSLv2Hello so we are stuck with it for now.
- // assertFalse(engineProtocols.contains("SSLv2Hello"), "SSLv2Hello should not be enabled by default");
- }
-
- @Test
- public void testCreateSslContextJksStoreJDK() throws Exception {
- SslOptions options = createJksSslOptions();
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- assertEquals("TLS", context.getProtocol());
- }
-
- @Test
- public void testCreateSslContextJksStoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- // TODO There is no means currently of getting the protocol from the netty SslContext.
- // assertEquals("TLS", context.getProtocol());
- }
-
- @Test
- public void testCreateSslContextJksStoreWithConfiguredContextProtocolJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- String contextProtocol = "TLSv1.2";
- options.contextProtocol(contextProtocol);
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- assertEquals(contextProtocol, context.getProtocol());
- }
-
- @Test
- public void testCreateSslContextJksStoreWithConfiguredContextProtocolOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
- String contextProtocol = "TLSv1.2";
- options.contextProtocol(contextProtocol);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- // TODO There is no means currently of getting the protocol from the netty SslContext.
- // assertEquals(contextProtocol, context.getProtocol());
- }
-
- @Test
- public void testCreateSslContextNoKeyStorePasswordJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- options.keyStorePassword(null);
-
- assertThrows(UnrecoverableKeyException.class, () -> {
- SslSupport.createJdkSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextNoKeyStorePasswordOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
- options.keyStorePassword(null);
-
- assertThrows(UnrecoverableKeyException.class, () -> {
- SslSupport.createOpenSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextWrongKeyStorePasswordJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- options.keyStorePassword("wrong");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createJdkSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextWrongKeyStorePasswordOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
- options.keyStorePassword("wrong");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createOpenSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextBadPathToKeyStoreJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- options.keyStoreLocation(CLIENT_JKS_KEYSTORE + ".bad");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createJdkSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextBadPathToKeyStoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
- options.keyStoreLocation(CLIENT_JKS_KEYSTORE + ".bad");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createOpenSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextWrongTrustStorePasswordJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- options.trustStorePassword("wrong");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createJdkSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextWrongTrustStorePasswordOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
- options.trustStorePassword("wrong");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createOpenSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextBadPathToTrustStoreJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- options.trustStoreLocation(CLIENT_JKS_TRUSTSTORE + ".bad");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createJdkSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextBadPathToTrustStoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
- options.trustStoreLocation(CLIENT_JKS_TRUSTSTORE + ".bad");
-
- assertThrows(IOException.class, () -> {
- SslSupport.createOpenSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextJceksStoreJDK() throws Exception {
- SslOptions options = createJceksSslOptions();
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- assertEquals("TLS", context.getProtocol());
- }
-
- @Test
- public void testCreateSslContextJceksStoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJceksSslOptions();
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
- assertTrue(context.isClient());
- }
-
- @Test
- public void testCreateSslContextPkcs12StoreJDK() throws Exception {
- SslOptions options = createPkcs12SslOptions();
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- assertEquals("TLS", context.getProtocol());
- }
-
- @Test
- public void testCreateSslContextPkcs12StoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createPkcs12SslOptions();
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
- assertTrue(context.isClient());
- }
-
- @Test
- public void testCreateSslContextIncorrectStoreTypeJDK() throws Exception {
- SslOptions options = createPkcs12SslOptions();
- options.storeType(KEYSTORE_JCEKS_TYPE);
-
- assertThrows(IOException.class, () -> {
- SslSupport.createJdkSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslContextIncorrectStoreTypeOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createPkcs12SslOptions();
- options.storeType(KEYSTORE_JCEKS_TYPE);
-
- assertThrows(IOException.class, () -> {
- SslSupport.createOpenSslContext(options);
- });
- }
-
- @Test
- public void testCreateSslEngineFromPkcs12StoreJDK() throws Exception {
- SslOptions options = createPkcs12SslOptions();
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.isEmpty());
- }
-
- @Test
- public void testCreateSslEngineFromPkcs12StoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createPkcs12SslOptions();
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.isEmpty());
- }
-
- @Test
- public void testCreateSslEngineFromPkcs12StoreWithExplicitEnabledProtocolsJDK() throws Exception {
- SslOptions options = createPkcs12SslOptions(ENABLED_PROTOCOLS);
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- assertArrayEquals(ENABLED_PROTOCOLS, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromPkcs12StoreWithExplicitEnabledProtocolsOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createPkcs12SslOptions(ENABLED_PROTOCOLS);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- assertArrayEquals(ENABLED_OPENSSL_PROTOCOLS, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreJDK() throws Exception {
- SslOptions options = createJksSslOptions();
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.isEmpty());
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions();
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.isEmpty());
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledProtocolsJDK() throws Exception {
- SslOptions options = createJksSslOptions(ENABLED_PROTOCOLS);
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- assertArrayEquals(ENABLED_PROTOCOLS, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledProtocolsOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJksSslOptions(ENABLED_PROTOCOLS);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- assertArrayEquals(ENABLED_OPENSSL_PROTOCOLS, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitDisabledProtocolsJDK() throws Exception {
- // Discover the default enabled protocols
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createSSLEngineDirectly(options);
- String[] protocols = directEngine.getEnabledProtocols();
- assertTrue(protocols.length > 0, "There were no initial protocols to choose from!");
-
- // Pull out one to disable specifically
- String[] disabledProtocol = new String[] { protocols[protocols.length - 1] };
- String[] trimmedProtocols = Arrays.copyOf(protocols, protocols.length - 1);
- options.disabledProtocols(disabledProtocol);
- SSLContext context = SslSupport.createJdkSslContext(options);
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
-
- // verify the option took effect
- assertNotNull(engine);
- assertArrayEquals(trimmedProtocols, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitDisabledProtocolsOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- // Discover the default enabled protocols
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createOpenSSLEngineDirectly(options);
- String[] protocols = directEngine.getEnabledProtocols();
- assertTrue(protocols.length > 0, "There were no initial protocols to choose from!");
-
- // Pull out one to disable specifically
- String[] disabledProtocol = new String[] { protocols[protocols.length - 1] };
- String[] trimmedProtocols = Arrays.copyOf(protocols, protocols.length - 1);
- options.disabledProtocols(disabledProtocol);
- SslContext context = SslSupport.createOpenSslContext(options);
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
-
- // verify the option took effect
- assertNotNull(engine);
- assertArrayEquals(trimmedProtocols, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledAndDisabledProtocolsJDK() throws Exception {
- // Discover the default enabled protocols
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createSSLEngineDirectly(options);
- String[] protocols = directEngine.getEnabledProtocols();
- assertTrue(protocols.length > 1, "There were no initial protocols to choose from!");
-
- // Pull out two to enable, and one to disable specifically
- String protocol1 = protocols[0];
- String protocol2 = protocols[1];
- String[] enabledProtocols = new String[] { protocol1, protocol2 };
- String[] disabledProtocol = new String[] { protocol1 };
- String[] remainingProtocols = new String[] { protocol2 };
- options.enabledProtocols(enabledProtocols);
- options.disabledProtocols(disabledProtocol);
- SSLContext context = SslSupport.createJdkSslContext(options);
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
-
- // verify the option took effect, that the disabled protocols were removed from the enabled list.
- assertNotNull(engine);
- assertArrayEquals(remainingProtocols, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledAndDisabledProtocolsOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- // Discover the default enabled protocols
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createOpenSSLEngineDirectly(options);
- String[] protocols = directEngine.getEnabledProtocols();
- assertTrue(protocols.length > 1, "There were no initial protocols to choose from!");
-
- // Pull out two to enable, and one to disable specifically
- String protocol1 = protocols[0];
- String protocol2 = protocols[1];
- String[] enabledProtocols = new String[] { protocol1, protocol2 };
- String[] disabledProtocol = new String[] { protocol1 };
- String[] remainingProtocols = new String[] { protocol2 };
- options.enabledProtocols(enabledProtocols);
- options.disabledProtocols(disabledProtocol);
- SslContext context = SslSupport.createOpenSslContext(options);
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
-
- // Because Netty cannot currently disable SSLv2Hello in OpenSSL we need to account for it popping up.
- ArrayList<String> remainingProtocolsList = new ArrayList<>(Arrays.asList(remainingProtocols));
- if (!remainingProtocolsList.contains("SSLv2Hello")) {
- remainingProtocolsList.add(0, "SSLv2Hello");
- }
-
- remainingProtocols = remainingProtocolsList.toArray(new String[remainingProtocolsList.size()]);
-
- // verify the option took effect, that the disabled protocols were removed from the enabled list.
- assertNotNull(engine);
- assertEquals(remainingProtocolsList.size(), engine.getEnabledProtocols().length, "Enabled protocols not as expected");
- assertTrue(remainingProtocolsList.containsAll(Arrays.asList(engine.getEnabledProtocols())), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledCiphersJDK() throws Exception {
- // Discover the default enabled ciphers
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createSSLEngineDirectly(options);
- String[] ciphers = directEngine.getEnabledCipherSuites();
- assertTrue(ciphers.length > 0, "There were no initial ciphers to choose from!");
-
- // Pull out one to enable specifically
- String cipher = ciphers[0];
- String[] enabledCipher = new String[] { cipher };
- options.enabledCipherSuites(enabledCipher);
- SSLContext context = SslSupport.createJdkSslContext(options);
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
-
- // verify the option took effect
- assertNotNull(engine);
- assertArrayEquals(enabledCipher, engine.getEnabledCipherSuites(), "Enabled ciphers not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledCiphersOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- // Discover the default enabled ciphers
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createOpenSSLEngineDirectly(options);
- String[] ciphers = directEngine.getEnabledCipherSuites();
- assertTrue(ciphers.length > 0, "There were no initial ciphers to choose from!");
-
- // Pull out one to enable specifically
- String cipher = ciphers[0];
- String[] enabledCipher = new String[] { cipher };
- options.enabledCipherSuites(enabledCipher);
- SslContext context = SslSupport.createOpenSslContext(options);
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
-
- // verify the option took effect
- assertNotNull(engine);
- assertArrayEquals(enabledCipher, engine.getEnabledCipherSuites(), "Enabled ciphers not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitDisabledCiphersJDK() throws Exception {
- // Discover the default enabled ciphers
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createSSLEngineDirectly(options);
- String[] ciphers = directEngine.getEnabledCipherSuites();
- assertTrue(ciphers.length > 0, "There were no initial ciphers to choose from!");
-
- // Pull out one to disable specifically
- String[] disabledCipher = new String[] { ciphers[ciphers.length - 1] };
- String[] trimmedCiphers = Arrays.copyOf(ciphers, ciphers.length - 1);
- options.disabledCipherSuites(disabledCipher);
- SSLContext context = SslSupport.createJdkSslContext(options);
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
-
- // verify the option took effect
- assertNotNull(engine);
- assertArrayEquals(trimmedCiphers, engine.getEnabledCipherSuites(), "Enabled ciphers not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitDisabledCiphersOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- // Discover the default enabled ciphers
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createOpenSSLEngineDirectly(options);
- String[] ciphers = directEngine.getEnabledCipherSuites();
- assertTrue(ciphers.length > 0, "There were no initial ciphers to choose from!");
-
- // Pull out one to disable specifically
- String[] disabledCipher = new String[] { ciphers[ciphers.length - 1] };
- String[] trimmedCiphers = Arrays.copyOf(ciphers, ciphers.length - 1);
- options.disabledCipherSuites(disabledCipher);
- SslContext context = SslSupport.createOpenSslContext(options);
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
-
- // verify the option took effect
- assertNotNull(engine);
- assertArrayEquals(trimmedCiphers, engine.getEnabledCipherSuites(), "Enabled ciphers not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledAndDisabledCiphersJDK() throws Exception {
- // Discover the default enabled ciphers
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createSSLEngineDirectly(options);
- String[] ciphers = directEngine.getEnabledCipherSuites();
- assertTrue(ciphers.length > 1, "There werent enough initial ciphers to choose from!");
-
- // Pull out two to enable, and one to disable specifically
- String cipher1 = ciphers[0];
- String cipher2 = ciphers[1];
- String[] enabledCiphers = new String[] { cipher1, cipher2 };
- String[] disabledCipher = new String[] { cipher1 };
- String[] remainingCipher = new String[] { cipher2 };
- options.enabledCipherSuites(enabledCiphers);
- options.disabledCipherSuites(disabledCipher);
- SSLContext context = SslSupport.createJdkSslContext(options);
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
-
- // verify the option took effect, that the disabled ciphers were removed from the enabled list.
- assertNotNull(engine);
- assertArrayEquals(remainingCipher, engine.getEnabledCipherSuites(), "Enabled ciphers not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJksStoreWithExplicitEnabledAndDisabledCiphersOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- // Discover the default enabled ciphers
- SslOptions options = createJksSslOptions();
- SSLEngine directEngine = createOpenSSLEngineDirectly(options);
- String[] ciphers = directEngine.getEnabledCipherSuites();
- assertTrue(ciphers.length > 1, "There werent enough initial ciphers to choose from!");
-
- // Pull out two to enable, and one to disable specifically
- String cipher1 = ciphers[0];
- String cipher2 = ciphers[1];
- String[] enabledCiphers = new String[] { cipher1, cipher2 };
- String[] disabledCipher = new String[] { cipher1 };
- String[] remainingCipher = new String[] { cipher2 };
- options.enabledCipherSuites(enabledCiphers);
- options.disabledCipherSuites(disabledCipher);
- SslContext context = SslSupport.createOpenSslContext(options);
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
-
- // verify the option took effect, that the disabled ciphers were removed from the enabled list.
- assertNotNull(engine);
- assertArrayEquals(remainingCipher, engine.getEnabledCipherSuites(), "Enabled ciphers not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJceksStoreJDK() throws Exception {
- SslOptions options = createJceksSslOptions();
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.isEmpty());
- }
-
- @Test
- public void testCreateSslEngineFromJceksStoreOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = createJceksSslOptions();
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- assertFalse(engineProtocols.isEmpty());
- }
-
- @Test
- public void testCreateSslEngineFromJceksStoreWithExplicitEnabledProtocolsJDK() throws Exception {
- SslOptions options = createJceksSslOptions(ENABLED_PROTOCOLS);
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- assertArrayEquals(ENABLED_PROTOCOLS, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineFromJceksStoreWithExplicitEnabledProtocolsOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- // Try and disable all but the one we really want but for now expect that this one plus SSLv2Hello
- // is going to come back until the netty code can successfully disable them all.
- SslOptions options = createJceksSslOptions(ENABLED_PROTOCOLS);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- assertArrayEquals(ENABLED_OPENSSL_PROTOCOLS, engine.getEnabledProtocols(), "Enabled protocols not as expected");
- }
-
- @Test
- public void testCreateSslEngineWithVerifyHostJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- options.verifyHost(true);
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- assertEquals("HTTPS", engine.getSSLParameters().getEndpointIdentificationAlgorithm());
- }
-
- @Test
- public void testCreateSslEngineWithVerifyHostOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
- assumeTrue(OpenSsl.supportsHostnameValidation());
-
- SslOptions options = createJksSslOptions();
- options.verifyHost(true);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- assertEquals("HTTPS", engine.getSSLParameters().getEndpointIdentificationAlgorithm());
- }
-
- @Test
- public void testCreateSslEngineWithoutVerifyHostJDK() throws Exception {
- SslOptions options = createJksSslOptions();
- options.verifyHost(false);
-
- SSLContext context = SslSupport.createJdkSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createJdkSslEngine(null, -1, context, options);
- assertNotNull(engine);
-
- assertNull(engine.getSSLParameters().getEndpointIdentificationAlgorithm());
- }
-
- @Test
- public void testCreateSslEngineWithoutVerifyHostOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
- assumeTrue(OpenSsl.supportsHostnameValidation());
-
- SslOptions options = createJksSslOptions();
- options.verifyHost(false);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- assertNotNull(context);
-
- SSLEngine engine = SslSupport.createOpenSslEngine(BufferAllocator.onHeapUnpooled(), null, -1, context, options);
- assertNotNull(engine);
-
- assertNull(engine.getSSLParameters().getEndpointIdentificationAlgorithm());
- }
-
- @Test
- public void testCreateSslContextWithKeyAliasWhichDoesntExist() throws Exception {
- SslOptions options = createJksSslOptions();
- options.keyAlias(ALIAS_DOES_NOT_EXIST);
-
- try {
- SslSupport.createJdkSslContext(options);
- fail("Expected exception to be thrown");
- } catch (IllegalArgumentException iae) {
- // Expected
- }
- }
-
- @Test
- public void testCreateSslContextWithKeyAliasWhichRepresentsNonKeyEntry() throws Exception {
- SslOptions options = createJksSslOptions();
- options.keyAlias(ALIAS_CA_CERT);
-
- try {
- SslSupport.createJdkSslContext(options);
- fail("Expected exception to be thrown");
- } catch (IllegalArgumentException iae) {
- // Expected
- }
- }
-
- @Test
- public void testIsOpenSSLPossible() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = new SslOptions();
- options.allowNativeSSL(false);
- assertFalse(SslSupport.isOpenSSLPossible(options));
-
- options.allowNativeSSL(true);
- assertTrue(SslSupport.isOpenSSLPossible(options));
- }
-
- @Test
- public void testIsOpenSSLPossibleWhenHostNameVerificationConfigured() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
- assumeTrue(OpenSsl.supportsHostnameValidation());
-
- SslOptions options = new SslOptions();
- options.allowNativeSSL(true);
-
- options.verifyHost(false);
- assertTrue(SslSupport.isOpenSSLPossible(options));
-
- options.verifyHost(true);
- assertTrue(SslSupport.isOpenSSLPossible(options));
- }
-
- @Test
- public void testIsOpenSSLPossibleWhenKeyAliasIsSpecified() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
- assumeTrue(OpenSsl.supportsHostnameValidation());
-
- SslOptions options = new SslOptions();
- options.allowNativeSSL(true);
- options.keyAlias("alias");
-
- assertFalse(SslSupport.isOpenSSLPossible(options));
- }
-
- @Test
- public void testCreateSslHandlerJDK() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = new SslOptions();
- options.sslEnabled(true);
- options.allowNativeSSL(false);
-
- SslHandler handler = SslSupport.createSslHandler(null, null, -1, options);
- assertNotNull(handler);
- assertFalse(handler.engine() instanceof OpenSslEngine);
- }
-
- @Test
- public void testCreateSslHandlerOpenSSL() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = new SslOptions();
- options.allowNativeSSL(true);
-
- SslHandler handler = SslSupport.createSslHandler(BufferAllocator.onHeapUnpooled(), null, -1, options);
- assertNotNull(handler);
- assertTrue(handler.engine() instanceof OpenSslEngine);
- }
-
- @Test
- public void testCreateOpenSSLEngineFailsWhenAllocatorMissing() throws Exception {
- assumeTrue(OpenSsl.isAvailable());
- assumeTrue(OpenSsl.supportsKeyManagerFactory());
-
- SslOptions options = new SslOptions();
- options.allowNativeSSL(true);
-
- SslContext context = SslSupport.createOpenSslContext(options);
- try {
- SslSupport.createOpenSslEngine(null, null, -1, context, options);
- fail("Should throw IllegalArgumentException for null allocator.");
- } catch (IllegalArgumentException iae) {}
- }
-
- private SslOptions createJksSslOptions() {
- return createJksSslOptions(null);
- }
-
- private SslOptions createJksSslOptions(String[] enabledProtocols) {
- SslOptions options = new SslOptions();
-
- options.sslEnabled(true);
- options.keyStoreLocation(CLIENT_JKS_KEYSTORE);
- options.trustStoreLocation(CLIENT_JKS_TRUSTSTORE);
- options.storeType(KEYSTORE_JKS_TYPE);
- options.keyStorePassword(PASSWORD);
- options.trustStorePassword(PASSWORD);
- if (enabledProtocols != null) {
- options.enabledProtocols(enabledProtocols);
- }
-
- return options;
- }
-
- private SslOptions createJceksSslOptions() {
- return createJceksSslOptions(null);
- }
-
- private SslOptions createJceksSslOptions(String[] enabledProtocols) {
- SslOptions options = new SslOptions();
-
- options.sslEnabled(true);
- options.keyStoreLocation(CLIENT_JCEKS_KEYSTORE);
- options.trustStoreLocation(CLIENT_JCEKS_TRUSTSTORE);
- options.storeType(KEYSTORE_JCEKS_TYPE);
- options.keyStorePassword(PASSWORD);
- options.trustStorePassword(PASSWORD);
- if (enabledProtocols != null) {
- options.enabledProtocols(enabledProtocols);
- }
-
- return options;
- }
-
- private SslOptions createPkcs12SslOptions() {
- return createPkcs12SslOptions(null);
- }
-
- private SslOptions createPkcs12SslOptions(String[] enabledProtocols) {
- SslOptions options = new SslOptions();
-
- options.keyStoreLocation(CLIENT_PKCS12_KEYSTORE);
- options.trustStoreLocation(CLIENT_PKCS12_TRUSTSTORE);
- options.storeType(KEYSTORE_PKCS12_TYPE);
- options.keyStorePassword(PASSWORD);
- options.trustStorePassword(PASSWORD);
- if (enabledProtocols != null) {
- options.enabledProtocols(enabledProtocols);
- }
-
- return options;
- }
-
- private SSLEngine createSSLEngineDirectly(SslOptions options) throws Exception {
- SSLContext context = SslSupport.createJdkSslContext(options);
- SSLEngine engine = context.createSSLEngine();
- return engine;
- }
-
- private SSLEngine createOpenSSLEngineDirectly(SslOptions options) throws Exception {
- SslContext context = SslSupport.createOpenSslContext(options);
- SSLEngine engine = context.newEngine(BufferAllocator.onHeapUnpooled());
- return engine;
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslTransportTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslTransportTest.java
deleted file mode 100644
index 6083305f..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/SslTransportTest.java
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.transport.Transport;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.Timeout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Test basic functionality of the Netty based TCP Transport running in secure mode (SSL).
- */
-@Timeout(30)
-public class SslTransportTest extends TcpTransportTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(SslTransportTest.class);
-
- public static final String PASSWORD = "password";
- public static final String SERVER_KEYSTORE = "src/test/resources/broker-jks.keystore";
- public static final String SERVER_TRUSTSTORE = "src/test/resources/broker-jks.truststore";
- public static final String SERVER_WRONG_HOST_KEYSTORE = "src/test/resources/broker-wrong-host-jks.keystore";
- public static final String CLIENT_KEYSTORE = "src/test/resources/client-jks.keystore";
- public static final String CLIENT_MULTI_KEYSTORE = "src/test/resources/client-multiple-keys-jks.keystore";
- public static final String CLIENT_TRUSTSTORE = "src/test/resources/client-jks.truststore";
- public static final String OTHER_CA_TRUSTSTORE = "src/test/resources/other-ca-jks.truststore";
- public static final String SERVER_CLASSPATH_KEYSTORE = "classpath:broker-jks.keystore";
- public static final String SERVER_CLASSPATH_TRUSTSTORE = "classpath:broker-jks.truststore";
-
- public static final String CLIENT_KEY_ALIAS = "client";
- public static final String CLIENT_DN = "O=Client,CN=client";
- public static final String CLIENT2_KEY_ALIAS = "client2";
- public static final String CLIENT2_DN = "O=Client2,CN=client2";
-
- public static final String KEYSTORE_TYPE = "jks";
-
- @Test
- public void testConnectToServerWithoutTrustStoreFails() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptionsWithoutTrustStore(false));
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- fail("Should have failed to connect to the server: " + HOSTNAME + ":" + port);
- } catch (Exception e) {
- LOG.info("Connection failed to untrusted test server: {}:{}", HOSTNAME, port);
- }
-
- assertFalse(transport.isConnected());
-
- transport.close();
- }
-
- logTransportErrors();
-
- assertFalse(exceptions.isEmpty());
- }
-
- @Test
- public void testConnectToServerUsingUntrustedKeyFails() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- SslOptions sslOptions = createSSLOptions();
-
- sslOptions.trustStoreLocation(OTHER_CA_TRUSTSTORE);
- sslOptions.trustStorePassword(PASSWORD);
-
- Transport transport = createTransport(createTransportOptions(), sslOptions);
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- fail("Should have failed to connect to the server: " + HOSTNAME + ":" + port);
- } catch (Exception e) {
- LOG.info("Connection failed to untrusted test server: {}:{}", HOSTNAME, port);
- }
-
- assertFalse(transport.isConnected());
-
- transport.close();
- }
- }
-
- @Test
- public void testConnectToServerWithWrongKeyStorePasswordFails() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
- final CountDownLatch errored = new CountDownLatch(1);
- final SslOptions sslOptions = createSSLOptions();
-
- sslOptions.keyStoreLocation(CLIENT_KEYSTORE);
- sslOptions.keyStorePassword("wrong");
-
- Transport transport = createTransport(createTransportOptions(), sslOptions);
- transport.connect(HOSTNAME, port, new NettyTransportListener() {
-
- @Override
- public void transportError(Throwable cause) {
- LOG.info("Transport error caught: {}", cause.getMessage(), cause);
- errored.countDown();
- }
- });
-
- assertTrue(errored.await(5, TimeUnit.SECONDS));
-
- try {
- transport.awaitConnect();
- fail("Should have failed to connect to the server: " + HOSTNAME + ":" + port);
- } catch (Exception e) {
- LOG.info("Connection failed when key store password was incorrect: {}:{}", HOSTNAME, port);
- }
-
- assertFalse(transport.isConnected());
-
- transport.close();
- }
- }
-
- @Test
- public void testConnectToServerWithWrongTrustStorePasswordFails() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
- final CountDownLatch errored = new CountDownLatch(1);
- final SslOptions sslOptions = createSSLOptions();
-
- sslOptions.trustStoreLocation(CLIENT_TRUSTSTORE);
- sslOptions.trustStorePassword("wrong");
-
- Transport transport = createTransport(createTransportOptions(), sslOptions);
- transport.connect(HOSTNAME, port, new NettyTransportListener() {
-
- @Override
- public void transportError(Throwable cause) {
- LOG.info("Transport error caught: {}", cause.getMessage(), cause);
- errored.countDown();
- }
- });
-
- assertTrue(errored.await(5, TimeUnit.SECONDS));
-
- try {
- transport.awaitConnect();
- fail("Should have failed to connect to the server: " + HOSTNAME + ":" + port);
- } catch (Exception e) {
- LOG.info("Connection failed when trust store password was incorrect: {}:{}", HOSTNAME, port);
- }
-
- assertFalse(transport.isConnected());
-
- transport.close();
- }
- }
-
- @Test
- public void testConnectToServerClientTrustsAll() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptionsWithoutTrustStore(true));
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connection established to test server: {}:{}", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertTrue(transport.isSecure());
-
- transport.close();
- }
-
- logTransportErrors();
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testConnectToServerWithServerClasspathStores() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createServerClasspathSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connection established to test server: {}:{}", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertTrue(transport.isSecure());
-
- transport.close();
- }
-
- logTransportErrors();
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testConnectWithNeedClientAuth() throws Exception {
- try (NettyEchoServer server = createEchoServer(true)) {
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connection established to test server: {}:{}", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertTrue(transport.isSecure());
-
- // Verify there was a certificate sent to the server
- server.getSslHandler().handshakeFuture().asStage().await(2, TimeUnit.SECONDS);
-
- assertTrue(server.getSslHandler().handshakeFuture().isSuccess(), "Server handshake did not complete in allotted time");
- assertNotNull(server.getSslHandler().engine().getSession().getPeerCertificates());
-
- transport.close();
- }
-
- logTransportErrors();
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testConnectWithSpecificClientAuthKeyAlias1() throws Exception {
- doClientAuthAliasTestImpl(CLIENT_KEY_ALIAS, CLIENT_DN);
- }
-
- @Test
- public void testConnectWithSpecificClientAuthKeyAlias2() throws Exception {
- doClientAuthAliasTestImpl(CLIENT2_KEY_ALIAS, CLIENT2_DN);
- }
-
- private void doClientAuthAliasTestImpl(String alias, String expectedDN) throws Exception, URISyntaxException, IOException, InterruptedException {
- try (NettyEchoServer server = createEchoServer(true)) {
- server.start();
-
- final int port = server.getServerPort();
-
- SslOptions sslOptions = createSSLOptions();
- sslOptions.keyStoreLocation(CLIENT_MULTI_KEYSTORE);
- sslOptions.keyAlias(alias);
-
- Transport transport = createTransport(createTransportOptions(), sslOptions);
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connection established to test server: {}:{}", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertTrue(transport.isSecure());
-
- server.getSslHandler().handshakeFuture().asStage().await(2, TimeUnit.SECONDS);
-
- assertTrue(server.getSslHandler().handshakeFuture().isSuccess(), "Server handshake did not complete in allotted time");
-
- Certificate[] peerCertificates = server.getSslHandler().engine().getSession().getPeerCertificates();
- assertNotNull(peerCertificates);
-
- Certificate cert = peerCertificates[0];
- assertTrue(cert instanceof X509Certificate);
- String dn = ((X509Certificate)cert).getSubjectX500Principal().getName();
- assertEquals(expectedDN, dn, "Unexpected certificate DN");
-
- transport.close();
- }
-
- logTransportErrors();
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testConnectToServerVerifyHost() throws Exception {
- doConnectToServerVerifyHostTestImpl(true);
- }
-
- @Test
- public void testConnectToServerNoVerifyHost() throws Exception {
- doConnectToServerVerifyHostTestImpl(false);
- }
-
- private void doConnectToServerVerifyHostTestImpl(boolean verifyHost) throws Exception, URISyntaxException, IOException, InterruptedException {
- SslOptions serverOptions = createServerSSLOptions();
- serverOptions.keyStoreLocation(SERVER_WRONG_HOST_KEYSTORE);
-
- try (NettyEchoServer server = createEchoServer(serverOptions)) {
- server.start();
-
- final int port = server.getServerPort();
-
- SslOptions clientOptions = createSSLOptionsIsVerify(verifyHost);
-
- if (verifyHost) {
- assertTrue(clientOptions.verifyHost(), "Expected verifyHost to be true");
- } else {
- assertFalse(clientOptions.verifyHost(), "Expected verifyHost to be false");
- }
-
- Transport transport = createTransport(createTransportOptions(), clientOptions);
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- if (verifyHost) {
- fail("Should not have connected to the server: " + HOSTNAME + ":" + port);
- }
- } catch (Exception e) {
- if (verifyHost) {
- LOG.info("Connection failed to test server: {}:{} as expected.", HOSTNAME, port);
- } else {
- LOG.error("Failed to connect to test server: {}:{}" + HOSTNAME, port, e);
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
- }
-
- assertNotNull(transport.getSslOptions());
- assertEquals(verifyHost, transport.getSslOptions().verifyHost());
-
- if (verifyHost) {
- assertFalse(transport.isConnected());
- } else {
- assertTrue(transport.isConnected());
- }
-
- transport.close();
- }
- }
-
- @Override
- protected SslOptions createSSLOptions() {
- return createSSLOptionsIsVerify(false);
- }
-
- protected SslOptions createSSLOptionsIsVerify(boolean verifyHost) {
- SslOptions options = new SslOptions();
-
- options.sslEnabled(true);
- options.keyStoreLocation(CLIENT_KEYSTORE);
- options.keyStorePassword(PASSWORD);
- options.trustStoreLocation(CLIENT_TRUSTSTORE);
- options.trustStorePassword(PASSWORD);
- options.storeType(KEYSTORE_TYPE);
- options.verifyHost(verifyHost);
-
- return options;
- }
-
- protected SslOptions createSSLOptionsWithoutTrustStore(boolean trustAll) {
- SslOptions options = new SslOptions();
-
- options.sslEnabled(true);
- options.storeType(KEYSTORE_TYPE);
- options.trustAll(trustAll);
-
- return options;
- }
-
- @Override
- protected SslOptions createServerSSLOptions() {
- SslOptions options = new SslOptions();
-
- // Run the server in JDK mode for now to validate cross compatibility
- options.sslEnabled(true);
- options.keyStoreLocation(SERVER_KEYSTORE);
- options.keyStorePassword(PASSWORD);
- options.trustStoreLocation(SERVER_TRUSTSTORE);
- options.trustStorePassword(PASSWORD);
- options.storeType(KEYSTORE_TYPE);
- options.verifyHost(false);
-
- return options;
- }
-
- protected SslOptions createServerClasspathSSLOptions() {
- SslOptions options = new SslOptions();
-
- // Run the server in JDK mode for now to validate cross compatibility
- options.sslEnabled(true);
- options.keyStoreLocation(SERVER_CLASSPATH_KEYSTORE);
- options.keyStorePassword(PASSWORD);
- options.trustStoreLocation(SERVER_CLASSPATH_TRUSTSTORE);
- options.trustStorePassword(PASSWORD);
- options.storeType(KEYSTORE_TYPE);
- options.verifyHost(false);
-
- return options;
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/TcpTransportTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/TcpTransportTest.java
deleted file mode 100644
index 3999bcb3..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/TcpTransportTest.java
+++ /dev/null
@@ -1,1196 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.junit.jupiter.api.Assumptions.assumeFalse;
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.qpid.protonj2.buffer.ProtonBuffer;
-import org.apache.qpid.protonj2.buffer.ProtonBufferAllocator;
-import org.apache.qpid.protonj2.buffer.netty.Netty4ProtonBufferAllocator;
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.apache.qpid.protonj2.client.test.ImperativeClientTestCase;
-import org.apache.qpid.protonj2.client.test.Wait;
-import org.apache.qpid.protonj2.client.transport.Transport;
-import org.apache.qpid.protonj2.client.transport.TransportListener;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.RepeatedTest;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.junit.jupiter.api.Timeout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty.buffer.UnpooledByteBufAllocator;
-import io.netty.incubator.channel.uring.IOUring;
-import io.netty5.bootstrap.Bootstrap;
-import io.netty5.channel.IoHandler;
-import io.netty5.channel.MultithreadEventLoopGroup;
-import io.netty5.channel.SingleThreadEventLoop;
-import io.netty5.channel.epoll.Epoll;
-import io.netty5.channel.epoll.EpollHandler;
-import io.netty5.channel.kqueue.KQueue;
-import io.netty5.channel.kqueue.KQueueHandler;
-import io.netty5.util.ResourceLeakDetector;
-import io.netty5.util.ResourceLeakDetector.Level;
-
-/**
- * Test basic functionality of the Netty based TCP transport.
- */
-@Timeout(30)
-public class TcpTransportTest extends ImperativeClientTestCase {
-
- private static final Logger LOG = LoggerFactory.getLogger(TcpTransportTest.class);
-
- protected static final int SEND_BYTE_COUNT = 1024;
- protected static final String HOSTNAME = "localhost";
-
- protected volatile boolean transportInitialized;
- protected volatile boolean transportConnected;
- protected volatile boolean transportErrored;
- protected final List<Throwable> exceptions = new ArrayList<>();
- protected final List<ProtonBuffer> data = new ArrayList<>();
- protected final AtomicInteger bytesRead = new AtomicInteger();
-
- protected final TransportListener testListener = new NettyTransportListener();
-
- protected ProtonBufferAllocator allocator;
- protected Netty5IOContext context;
-
- @Override
- @BeforeEach
- public void setUp(TestInfo testInfo) throws Exception {
- super.setUp(testInfo);
-
- allocator = new Netty4ProtonBufferAllocator(UnpooledByteBufAllocator.DEFAULT);
- }
-
- @Override
- @AfterEach
- public void tearDown(TestInfo testInfo) throws Exception {
- super.tearDown(testInfo);
-
- if (context != null) {
- context.shutdown();
- context = null;
- }
-
- data.removeIf((buffer) -> {
- buffer.close();
- return true;
- });
- }
-
- @Test
- public void testCannotCreateWithIllegalArgs() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> new TcpTransport(null, createTransportOptions(), createSSLOptions()));
- assertThrows(IllegalArgumentException.class, () -> new TcpTransport(new Bootstrap(), null, createSSLOptions()));
- assertThrows(IllegalArgumentException.class, () -> new TcpTransport(new Bootstrap(), createTransportOptions(), null));
- }
-
- @Test
- public void testCloseOnNeverConnectedTransport() throws Exception {
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- assertFalse(transport.isConnected());
-
- transport.close();
-
- assertFalse(transportInitialized);
- assertFalse(transportConnected);
- assertFalse(transportErrored);
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testCannotCallConnectOnClosedTransport() throws Exception {
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
-
- transport.close();
-
- assertThrows(IllegalStateException.class, () -> transport.connect("localhost", 5672, testListener));
- }
-
- @Test
- public void testCreateWithBadHostOrPortThrowsIAE() throws Exception {
- Transport transport = createTransport(createTransportOptions().defaultTcpPort(-1), createSSLOptions().defaultSslPort(-1));
-
- try {
- transport.connect(HOSTNAME, -1, testListener);
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException iae) {
- }
-
- try {
- transport.connect(null, 5672, testListener);
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException iae) {
- }
-
- try {
- transport.connect("", 5672, testListener);
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException iae) {
- }
- }
-
- @Test
- public void testCreateWithNullOptionsThrowsIAE() throws Exception {
- try {
- new Netty5IOContext(null, null, getTestName());
- fail("Should have thrown NullPointerException");
- } catch (NullPointerException npe) {
- }
-
- try {
- new Netty5IOContext(createTransportOptions(), null, getTestName());
- fail("Should have thrown NullPointerException");
- } catch (NullPointerException npe) {
- }
-
- try {
- new Netty5IOContext(null, createSSLOptions(), getTestName());
- fail("Should have thrown NullPointerException");
- } catch (NullPointerException npe) {
- }
- }
-
- @Test
- public void testConnectWithoutRunningServer() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- server.close();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
-
- assertNull(transport.getTransportListener());
-
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- fail("Should have failed to connect to the server: " + HOSTNAME + ":" + port);
- } catch (Exception e) {
- LOG.info("Failed to connect to: {}:{} as expected.", HOSTNAME, port);
- }
-
- assertEquals(testListener, transport.getTransportListener());
- assertFalse(transport.isConnected());
-
- transport.close();
- }
-
- assertTrue(transportInitialized);
- assertFalse(transportConnected);
- assertTrue(transportErrored);
- assertFalse(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testConnectWithoutListenerFails() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
-
- try {
- transport.connect(HOSTNAME, port, null);
- fail("Should have failed to connect to the server: " + HOSTNAME + ":" + port);
- } catch (IllegalArgumentException e) {
- LOG.info("Failed to connect to: {}:{} as expected.", HOSTNAME, port);
- }
-
- assertFalse(transport.isConnected());
-
- transport.close();
- }
- }
-
- @Test
- public void testConnectToServer() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
-
- final URI remoteURI = transport.getRemoteURI();
-
- if (transport.isSecure()) {
- if (transport.getTransportOptions().useWebSockets()) {
- assertEquals(remoteURI.getScheme(), "wss");
- } else {
- assertEquals(remoteURI.getScheme(), "ssl");
- }
- } else {
- if (transport.getTransportOptions().useWebSockets()) {
- assertEquals(remoteURI.getScheme(), "ws");
- } else {
- assertEquals(remoteURI.getScheme(), "tcp");
- }
- }
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertTrue(transportInitialized);
- assertTrue(transportConnected);
- assertFalse(transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testMultipleConnectionsToServer() throws Exception {
- final int CONNECTION_COUNT = 10;
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- List<Transport> transports = new ArrayList<>();
-
- Netty5IOContext context = createContext(createTransportOptions(), createSSLOptions());
-
- for (int i = 0; i < CONNECTION_COUNT; ++i) {
- Transport transport = context.newTransport();
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- assertTrue(transport.isConnected());
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- transports.add(transport);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
- }
-
- for (Transport transport : transports) {
- transport.close();
- }
- }
-
- assertTrue(transportInitialized);
- assertFalse(transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testMultipleConnectionsSendReceive() throws Exception {
- final int CONNECTION_COUNT = 10;
- final int FRAME_SIZE = 8;
-
- ProtonBuffer sendBuffer = allocator.allocate(FRAME_SIZE);
- for (int i = 0; i < 8; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- List<Transport> transports = new ArrayList<>();
-
- Netty5IOContext context = createContext(createTransportOptions(), createSSLOptions());
-
- for (int i = 0; i < CONNECTION_COUNT; ++i) {
- Transport transport = context.newTransport();
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- transport.writeAndFlush(sendBuffer.copy());
- transports.add(transport);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
- }
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- LOG.debug("Checking completion: read {} expecting {}", bytesRead.get(), (FRAME_SIZE * CONNECTION_COUNT));
- return bytesRead.get() == (FRAME_SIZE * CONNECTION_COUNT);
- }
- }, 10000, 50));
-
- for (Transport transport : transports) {
- transport.close();
- }
- }
-
- assertTrue(exceptions.isEmpty());
- }
-
- @RepeatedTest(1)
- public void testDetectServerClose() throws Exception {
- Transport transport = null;
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- return server.getClientCount() == 1;
- }
- }, 10000, 50));
- }
-
- final Transport connectedTransport = transport;
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- return !connectedTransport.isConnected();
- }
- }, 10000, 50));
-
- assertTrue(data.isEmpty());
-
- try {
- transport.close();
- } catch (Exception ex) {
- fail("Close of a disconnect transport should not generate errors");
- }
- }
-
- @Test
- public void testZeroSizedSentNoErrorsWriteAndFlush() throws Exception {
- testZeroSizedSentNoErrors(true);
- }
-
- @Test
- public void testZeroSizedSentNoErrorsWriteThenFlush() throws Exception {
- testZeroSizedSentNoErrors(false);
- }
-
- private void testZeroSizedSentNoErrors(boolean writeAndFlush) throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- final ProtonBuffer sendBuffer = allocator.allocate(0);
-
- if (writeAndFlush) {
- transport.writeAndFlush(sendBuffer);
- } else {
- transport.write(sendBuffer);
- transport.flush();
- }
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testUseAllocatorToCreateFixedSizeOutputBuffer() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- ProtonBuffer buffer = transport.getBufferAllocator().allocate(64).implicitGrowthLimit(512);
-
- assertEquals(64, buffer.capacity());
- assertEquals(512, buffer.implicitGrowthLimit());
-
- transport.writeAndFlush(buffer);
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testUseAllocatorToCreateFixedSizeHeapBuffer() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- ProtonBuffer buffer = transport.getBufferAllocator().allocate(64).implicitGrowthLimit(512);
-
- assertEquals(64, buffer.capacity());
- assertEquals(512, buffer.implicitGrowthLimit());
-
- transport.writeAndFlush(buffer);
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testDataSentWithWriteAndThenFlushedIsReceived() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- ProtonBuffer sendBuffer = transport.getBufferAllocator().outputBuffer(SEND_BYTE_COUNT);
- for (int i = 0; i < SEND_BYTE_COUNT; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- transport.write(sendBuffer, () -> LOG.debug("Netty reports write complete"));
- LOG.trace("Flush of Transport happens now");
- transport.flush();
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- return !data.isEmpty();
- }
- }, 10000, 50));
-
- assertEquals(SEND_BYTE_COUNT, data.get(0).getReadableBytes());
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testDataSentWithinCompositeBufferIsReceived() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- ProtonBuffer sendBuffer1 = transport.getBufferAllocator().outputBuffer(SEND_BYTE_COUNT);
- for (int i = 0; i < SEND_BYTE_COUNT; ++i) {
- sendBuffer1.writeByte((byte) 'A');
- }
- ProtonBuffer sendBuffer2 = transport.getBufferAllocator().outputBuffer(SEND_BYTE_COUNT + 10);
- for (int i = 0; i < SEND_BYTE_COUNT + 10; ++i) {
- sendBuffer2.writeByte((byte) 'A');
- }
-
- ProtonBuffer sendBuffer = transport.getBufferAllocator().composite(new ProtonBuffer[] { sendBuffer1, sendBuffer2});
-
- transport.write(sendBuffer, () -> LOG.debug("Netty reports write complete"));
- LOG.trace("Flush of Transport happens now");
- transport.flush();
-
- sendBuffer.close();
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- return bytesRead.get() == SEND_BYTE_COUNT + SEND_BYTE_COUNT + 10;
- }
- }, 10000, 50));
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testDataSentWithWriteAndFlushIsReceived() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- ProtonBuffer sendBuffer = transport.getBufferAllocator().outputBuffer(SEND_BYTE_COUNT);
- for (int i = 0; i < SEND_BYTE_COUNT; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- transport.writeAndFlush(sendBuffer, () -> LOG.debug("Netty reports write complete"));
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- return !data.isEmpty();
- }
- }, 10000, 50));
-
- assertEquals(SEND_BYTE_COUNT, data.get(0).getReadableBytes());
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testMultipleDataPacketsSentAreReceived() throws Exception {
- doMultipleDataPacketsSentAndReceive(SEND_BYTE_COUNT, 1);
- }
-
- @Test
- public void testMultipleDataPacketsSentAreReceivedRepeatedly() throws Exception {
- doMultipleDataPacketsSentAndReceive(SEND_BYTE_COUNT, 10);
- }
-
- public void doMultipleDataPacketsSentAndReceive(final int byteCount, final int iterations) throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- final ProtonBuffer sendBuffer = allocator.allocate(byteCount);
-
- for (int i = 0; i < byteCount; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- for (int i = 0; i < iterations; ++i) {
- transport.writeAndFlush(sendBuffer.copy(true));
- }
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- return bytesRead.get() == (byteCount * iterations);
- }
- }, 10000, 50));
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testSendToClosedTransportFails() throws Exception {
- Transport transport = null;
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- transport.close();
-
- final ProtonBuffer sendBuffer = allocator.allocate(10);
-
- try {
- transport.writeAndFlush(sendBuffer);
- fail("Should throw on send of closed transport");
- } catch (IOException ex) {
- }
- }
- }
-
- @Test
- public void testConnectRunsInitializationMethod() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
- final CountDownLatch initialized = new CountDownLatch(1);
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, new NettyTransportListener() {
-
- @Override
- public void transportInitialized(Transport transport) {
- initialized.countDown();
- assertFalse(transport.isConnected());
- }
- });
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- initialized.await();
- transport.awaitConnect();
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
- assertEquals(0, initialized.getCount());
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testFailureInInitializationRoutineFailsConnect() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, new NettyTransportListener() {
-
- @Override
- public void transportInitialized(Transport transport) {
- throw new RuntimeException();
- }
- }).awaitConnect();
- fail("Should not have connected to the server at " + HOSTNAME + ":" + port);
- } catch (Exception e) {
- LOG.info("Failed to connect to: {}:{} as expected.", HOSTNAME, port);
- }
-
- assertFalse(transport.isConnected(), "Should not be connected");
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
-
- transport.close();
- }
-
- assertTrue(transportErrored);
- assertFalse(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Disabled("Used for checking for transport level leaks, my be unstable on CI.")
- @Test
- public void testSendToClosedTransportFailsButDoesNotLeak() throws Exception {
- Transport transport = null;
-
- ResourceLeakDetector.setLevel(Level.PARANOID);
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- for (int i = 0; i < 256; ++i) {
- transport = createTransport(createTransportOptions(), createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
-
- ProtonBuffer sendBuffer = transport.getBufferAllocator().outputBuffer(10 * 1024 * 1024);
- sendBuffer.writeBytes(new byte[] {0, 1, 2, 3, 4});
-
- transport.close();
-
- try {
- transport.writeAndFlush(sendBuffer);
- fail("Should throw on send of closed transport");
- } catch (IOException ex) {
- }
- }
-
- System.gc();
- }
- }
-
- @Test
- public void testCreateFailsIfUnknownPreferredNativeIOLayerSelected() throws Exception {
- TransportOptions options = createTransportOptions();
- options.allowNativeIO(true);
- options.nativeIOPreference("NATIVE-IO");
-
- assertThrows(IllegalArgumentException.class, () -> createTransport(options, createSSLOptions()));
- }
-
- @Test
- public void testConnectToServerWithEpollEnabled() throws Exception {
- doTestEpollSupport(true);
- }
-
- @Test
- public void testConnectToServerWithEpollDisabled() throws Exception {
- doTestEpollSupport(false);
- }
-
- private void doTestEpollSupport(boolean useEpoll) throws Exception {
- assumeTrue(Epoll.isAvailable());
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- TransportOptions options = createTransportOptions();
- options.allowNativeIO(useEpoll);
- options.nativeIOPreference("EPOLL");
- Transport transport = createTransport(options, createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
- assertEpoll("Transport should be using Epoll", useEpoll, transport);
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertFalse(transportErrored);
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Disabled("IU_Uring support not ready for Netty 5")
- @Test
- public void testConnectToServerWithIOUringEnabled() throws Exception {
- doTestIORingSupport(true);
- }
-
- @Disabled("IU_Uring support not ready for Netty 5")
- @Test
- public void testConnectToServerWithIOUringDisabled() throws Exception {
- doTestIORingSupport(false);
- }
-
- private void doTestIORingSupport(boolean useIOUring) throws Exception {
- assumeTrue(IOUring.isAvailable());
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- TransportOptions options = createTransportOptions();
- options.allowNativeIO(useIOUring);
- options.nativeIOPreference("IO_URING");
- Transport transport = createTransport(options, createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
- assertIOUring("Transport should be using URing", useIOUring, transport);
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertFalse(transportErrored);
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testConnectToServerWithKQueueEnabled() throws Exception {
- doTestKQueueSupport(true);
- }
-
- @Test
- public void testConnectToServerWithKQueueDisabled() throws Exception {
- doTestKQueueSupport(false);
- }
-
- private void doTestKQueueSupport(boolean useKQueue) throws Exception {
- assumeTrue(KQueue.isAvailable());
-
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- TransportOptions options = createTransportOptions();
- options.allowNativeIO(true);
- Transport transport = createTransport(options, createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
- assertKQueue("Transport should be using Kqueue", useKQueue, transport);
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testFallbackToNioWhenNativeIOConfiguredNotSupportedEpoll() throws Exception {
- assumeFalse(Epoll.isAvailable());
-
- doTestFallbackToNioWhenNativeLayerNotSupported(EpollSupport.NAME);
- }
-
- @Test
- public void testFallbackToNioWhenNativeIOConfiguredNotSupportedKQueue() throws Exception {
- assumeFalse(KQueue.isAvailable());
-
- doTestFallbackToNioWhenNativeLayerNotSupported(KQueueSupport.NAME);
- }
-
- private void doTestFallbackToNioWhenNativeLayerNotSupported(String nativeIOLayer) throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- int port = server.getServerPort();
-
- TransportOptions options = createTransportOptions();
- options.allowNativeIO(true);
- options.nativeIOPreference(nativeIOLayer);
-
- Transport transport = createTransport(options, createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should not have failed to connect to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertFalse(transportErrored);
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- protected Netty5IOContext createContext(TransportOptions options, SslOptions sslOptions) {
- if (context != null) {
- throw new IllegalStateException("Test already has a defined Netty IO Context");
- }
-
- return this.context = new Netty5IOContext(options, sslOptions, getTestName());
- }
-
- protected Transport createTransport(TransportOptions options, SslOptions sslOptions) {
- if (context != null) {
- throw new IllegalStateException("Test already has a defined Netty IO Context");
- } else {
- this.context = new Netty5IOContext(options, sslOptions, getTestName());
- }
-
- return context.newTransport();
- }
-
- protected TransportOptions createTransportOptions() {
- return new TransportOptions();
- }
-
- protected SslOptions createSSLOptions() {
- return new SslOptions().sslEnabled(false);
- }
-
- protected TransportOptions createServerTransportOptions() {
- return new TransportOptions();
- }
-
- protected SslOptions createServerSSLOptions() {
- return new SslOptions().sslEnabled(false);
- }
-
- protected void logTransportErrors() {
- if (!exceptions.isEmpty()) {
- for(Throwable ex : exceptions) {
- LOG.info("Transport sent exception: {}", ex, ex);
- }
- }
- }
-
- protected final NettyEchoServer createEchoServer() {
- return createEchoServer(false);
- }
-
- protected final NettyEchoServer createEchoServer(SslOptions options) {
- return createEchoServer(options, false);
- }
-
- protected final NettyEchoServer createEchoServer(boolean needClientAuth) {
- return createEchoServer(createServerSSLOptions(), needClientAuth);
- }
-
- protected final NettyEchoServer createEchoServer(SslOptions options, boolean needClientAuth) {
- return createEchoServer(createServerTransportOptions(), options, needClientAuth);
- }
-
- protected final NettyEchoServer createEchoServer(TransportOptions options) {
- return new NettyEchoServer(options, createServerSSLOptions(), false);
- }
-
- protected final NettyEchoServer createEchoServer(TransportOptions options, SslOptions sslOptions, boolean needClientAuth) {
- return new NettyEchoServer(options, sslOptions, needClientAuth);
- }
-
- public class NettyTransportListener implements TransportListener {
-
- @Override
- public void transportRead(ProtonBuffer incoming) {
- LOG.debug("Client has new incoming data of size: {}", incoming.getReadableBytes());
- bytesRead.addAndGet(incoming.getReadableBytes());
- data.add(incoming.transfer());
- }
-
- @Override
- public void transportError(Throwable cause) {
- LOG.info("Transport error caught: {}", cause.getMessage(), cause);
- transportErrored = true;
- exceptions.add(cause);
- }
-
- @Override
- public void transportConnected(Transport transport) {
- transportConnected = true;
- }
-
- @Override
- public void transportInitialized(Transport transport) {
- transportInitialized = true;
- }
- }
-
- private void assertEpoll(String message, boolean expected, Transport transport) throws Exception {
- assertEventLoopIoHandlerType(message, expected, transport ,EpollHandler.class);
- }
-
- private void assertKQueue(String message, boolean expected, Transport transport) throws Exception {
- assertEventLoopIoHandlerType(message, expected, transport, KQueueHandler.class);
- }
-
- private void assertIOUring(String message, boolean expected, Transport transport) throws Exception {
- //assertEventLoopIoHandlerType(message, expected, transport, IOUringHandler.class);
- fail("Netty 5 doesn't have IO_Uring support yet");
- }
-
- private static void assertEventLoopIoHandlerType(String message, boolean expected, Transport transport, Class<? extends IoHandler> ioHandlerClass) throws Exception {
- Field bootstrap = null;
- Class<?> transportType = transport.getClass();
-
- while (transportType != null && bootstrap == null) {
- try {
- bootstrap = transportType.getDeclaredField("bootstrap");
- } catch (NoSuchFieldException error) {
- transportType = transportType.getSuperclass();
- if (Object.class.equals(transportType)) {
- transportType = null;
- }
- }
- }
-
- assertNotNull(bootstrap, "Transport implementation unknown");
-
- bootstrap.setAccessible(true);
-
- final Bootstrap transportBootstrap = (Bootstrap) bootstrap.get(transport);
-
- assertTrue(MultithreadEventLoopGroup.class.isInstance(transportBootstrap.config().group()), message);
- assertTrue(SingleThreadEventLoop.class.isInstance(transportBootstrap.config().group().next()), message);
-
- Field ioHandlerField = null;
- Class<?> executorType = transportBootstrap.config().group().next().getClass();
-
- while (executorType != null && ioHandlerField == null) {
- try {
- ioHandlerField = executorType.getDeclaredField("ioHandler");
- } catch (NoSuchFieldException error) {
- executorType = executorType.getSuperclass();
- if (Object.class.equals(executorType)) {
- executorType = null;
- }
- }
- }
-
- assertNotNull(ioHandlerField, "EventLoop implementation unknown");
-
- ioHandlerField.setAccessible(true);
-
- final IoHandler ioHandlerRef = (IoHandler) ioHandlerField.get(transportBootstrap.config().group().next());
-
- if (expected) {
- assertTrue(ioHandlerClass.isInstance(ioHandlerRef), message);
- } else {
- assertFalse(ioHandlerClass.isInstance(ioHandlerRef), message);
- }
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/WebSocketTransportTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/WebSocketTransportTest.java
deleted file mode 100644
index 8b850b28..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/WebSocketTransportTest.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.qpid.protonj2.buffer.ProtonBuffer;
-import org.apache.qpid.protonj2.buffer.ProtonBufferAllocator;
-import org.apache.qpid.protonj2.client.SslOptions;
-import org.apache.qpid.protonj2.client.TransportOptions;
-import org.apache.qpid.protonj2.client.test.Wait;
-import org.apache.qpid.protonj2.client.transport.Transport;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.Timeout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.bootstrap.Bootstrap;
-import io.netty5.handler.codec.http.headers.HttpHeaders;
-import io.netty5.handler.codec.http.websocketx.WebSocketServerHandshakeCompletionEvent;
-
-/**
- * Test the Netty based WebSocket Transport
- */
-@Timeout(30)
-public class WebSocketTransportTest extends TcpTransportTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(WebSocketTransportTest.class);
-
- @Override
- protected TransportOptions createTransportOptions() {
- return new TransportOptions().useWebSockets(true);
- }
-
- @Override
- protected TransportOptions createServerTransportOptions() {
- return new TransportOptions().useWebSockets(true);
- }
-
- @Override
- @Test
- public void testCannotCreateWithIllegalArgs() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> new WebSocketTransport(null, createTransportOptions(), createSSLOptions()));
- assertThrows(IllegalArgumentException.class, () -> new WebSocketTransport(new Bootstrap(), null, createSSLOptions()));
- assertThrows(IllegalArgumentException.class, () -> new WebSocketTransport(new Bootstrap(), createTransportOptions(), null));
- }
-
- @Test
- public void testConnectToServerUsingCorrectPath() throws Exception {
- final String WEBSOCKET_PATH = "/testpath";
-
- try (NettyEchoServer server = createEchoServer()) {
- server.setWebSocketPath(WEBSOCKET_PATH);
- server.start();
-
- final int port = server.getServerPort();
-
- Transport transport = createTransport(createTransportOptions().webSocketPath(WEBSOCKET_PATH), createSSLOptions());
-
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport instanceof WebSocketTransport);
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
-
- transport.close();
-
- // Additional close should not fail or cause other problems.
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testConnectToServerUsingIncorrectPath() throws Exception {
- final String WEBSOCKET_PATH = "/testpath";
-
- try (NettyEchoServer server = createEchoServer()) {
- // No configured path means it won't match the requested one.
- server.start();
-
- final int port = server.getServerPort();
-
- server.close();
-
- Transport transport = createTransport(createTransportOptions().webSocketPath(WEBSOCKET_PATH), createSSLOptions());
-
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- fail("Should have failed to connect to the server: " + HOSTNAME + ":" + port);
- } catch (Exception e) {
- LOG.info("Failed to connect to: {}:{} as expected.", HOSTNAME, port);
- }
-
- assertTrue(transport instanceof WebSocketTransport);
- assertFalse(transport.isConnected());
-
- transport.close();
- }
-
- assertTrue(transportErrored);
- assertFalse(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- @Test
- public void testConnectionsSendReceiveLargeDataWhenFrameSizeAllowsIt() throws Exception {
- final int FRAME_SIZE = 8192;
-
- final ProtonBuffer sendBuffer = allocator.allocate(FRAME_SIZE);
- for (int i = 0; i < FRAME_SIZE; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- try (NettyEchoServer server = createEchoServer()) {
- // Server should pass the data through without issue with this size
- server.setMaxFrameSize(FRAME_SIZE);
- server.start();
-
- final int port = server.getServerPort();
-
- List<Transport> transports = new ArrayList<>();
-
- Transport transport = createTransport(createTransportOptions().webSocketMaxFrameSize(FRAME_SIZE), createSSLOptions());
-
- try {
- // The transport should allow for the size of data we sent.
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- transports.add(transport);
- transport.writeAndFlush(sendBuffer.copy());
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport instanceof WebSocketTransport);
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- LOG.debug("Checking completion: read {} expecting {}", bytesRead.get(), FRAME_SIZE);
- return bytesRead.get() == FRAME_SIZE || !transport.isConnected();
- }
- }, 10000, 50));
-
- assertTrue(transport.isConnected(), "Connection failed while receiving.");
-
- transport.close();
- }
-
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testConnectionReceivesFragmentedDataSingleWriteAndFlush() throws Exception {
- testConnectionReceivesFragmentedData(true);
- }
-
- @Test
- public void testConnectionReceivesFragmentedDataWriteThenFlush() throws Exception {
- testConnectionReceivesFragmentedData(false);
- }
-
- private void testConnectionReceivesFragmentedData(boolean writeAndFlush) throws Exception {
-
- final int FRAME_SIZE = 5317;
-
- final ProtonBuffer sendBuffer = allocator.allocate(FRAME_SIZE);
- for (int i = 0; i < FRAME_SIZE; ++i) {
- sendBuffer.writeByte((byte) ('A' + (i % 10)));
- }
-
- try (NettyEchoServer server = createEchoServer()) {
- server.setMaxFrameSize(FRAME_SIZE);
- // Server should fragment the data as it goes through
- server.setFragmentWrites(true);
- server.start();
-
- final int port = server.getServerPort();
-
- List<Transport> transports = new ArrayList<>();
-
- TransportOptions clientOptions = createTransportOptions();
- clientOptions.traceBytes(true);
- clientOptions.webSocketMaxFrameSize(FRAME_SIZE);
-
- NettyTransportListener wsListener = new NettyTransportListener();
-
- Transport transport = createTransport(clientOptions, createSSLOptions());
- try {
- transport.connect(HOSTNAME, port, wsListener).awaitConnect();
- transports.add(transport);
- if (writeAndFlush) {
- transport.writeAndFlush(allocator.allocate());
- transport.writeAndFlush(sendBuffer.copy());
- } else {
- transport.write(allocator.allocate());
- transport.write(sendBuffer.copy());
- transport.flush();
- }
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport instanceof WebSocketTransport);
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- LOG.debug("Checking completion: read {} expecting {}", bytesRead.get(), FRAME_SIZE);
- return bytesRead.get() == FRAME_SIZE || !transport.isConnected();
- }
- }, 10000, 50));
-
- assertTrue(transport.isConnected(), "Connection failed while receiving.");
-
- transport.close();
-
- assertEquals(2, data.size(), "Expected 2 data packets due to separate websocket frames");
-
- ProtonBuffer receivedBuffer = ProtonBufferAllocator.defaultAllocator().allocate(FRAME_SIZE);
- for (ProtonBuffer buf : data) {
- buf.copyInto(buf.getReadOffset(), receivedBuffer, receivedBuffer.getWriteOffset(), buf.getReadableBytes());
- receivedBuffer.advanceWriteOffset(buf.getReadableBytes());
- }
-
- assertEquals(FRAME_SIZE, receivedBuffer.getReadableBytes(), "Unexpected data length");
- assertEquals(sendBuffer, receivedBuffer, "Unexpected data");
- } finally {
- for (ProtonBuffer buf : data) {
- buf.close();
- }
- }
-
- assertTrue(exceptions.isEmpty());
- }
-
- @Test
- public void testConnectionsSendReceiveLargeDataFailsDueToMaxFrameSize() throws Exception {
- final int FRAME_SIZE = 1024;
-
- final ProtonBuffer sendBuffer = allocator.allocate(FRAME_SIZE);
- for (int i = 0; i < FRAME_SIZE; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- try (NettyEchoServer server = createEchoServer()) {
- // Server should pass the data through, client should choke on the incoming size.
- server.setMaxFrameSize(FRAME_SIZE);
- server.start();
-
- final int port = server.getServerPort();
-
- List<Transport> transports = new ArrayList<>();
-
- final Transport transport = createTransport(createTransportOptions().webSocketMaxFrameSize(FRAME_SIZE / 2), createSSLOptions());
-
- try {
- // Transport can't receive anything bigger so it should fail the connection
- // when data arrives that is larger than this value.
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- transports.add(transport);
- transport.writeAndFlush(sendBuffer.copy());
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport instanceof WebSocketTransport);
- assertTrue(Wait.waitFor(() -> !transport.isConnected()), "Transport should have lost connection");
- }
-
- assertFalse(exceptions.isEmpty());
- }
-
- @Test
- public void testTransportDetectsConnectionDropWhenServerEnforcesMaxFrameSize() throws Exception {
- final int FRAME_SIZE = 1024;
-
- final ProtonBuffer sendBuffer = allocator.allocate(FRAME_SIZE);
- for (int i = 0; i < FRAME_SIZE; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- try (NettyEchoServer server = createEchoServer()) {
- // Server won't accept the data as it's to large and will close the connection.
- server.setMaxFrameSize(FRAME_SIZE / 2);
- server.start();
-
- final int port = server.getServerPort();
-
- List<Transport> transports = new ArrayList<>();
-
- final Transport transport = createTransport(createTransportOptions().webSocketMaxFrameSize(FRAME_SIZE), createSSLOptions());
-
- assertTrue(transport instanceof WebSocketTransport);
-
- try {
- // Transport allows bigger frames in so that server is the one causing the failure.
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- transports.add(transport);
- transport.writeAndFlush(sendBuffer.copy());
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- try {
- transport.writeAndFlush(sendBuffer.copy());
- } catch (IOException e) {
- LOG.info("Transport send caught error:", e);
- return true;
- }
-
- return false;
- }
- }, 10000, 10), "Transport should have lost connection");
-
- transport.close();
- }
- }
-
- @Test
- public void testTransportConnectionDoesNotDropWhenServerAndClientUseCompressionWithLargePayloads() throws Exception {
- final int FRAME_SIZE = 16384; // This value would exceed the set max frame size without compression.
-
- final ProtonBuffer sendBuffer = allocator.allocate(FRAME_SIZE);
- for (int i = 0; i < FRAME_SIZE; ++i) {
- sendBuffer.writeByte((byte) 'A');
- }
-
- try (NettyEchoServer server = createEchoServer(createServerTransportOptions().webSocketCompression(true).traceBytes(true))) {
- // Server won't accept the data as it's to large and will close the connection.
- server.setMaxFrameSize(FRAME_SIZE / 2);
- server.start();
-
- final int port = server.getServerPort();
-
- List<Transport> transports = new ArrayList<>();
-
- final Transport transport = createTransport(createTransportOptions().webSocketMaxFrameSize(FRAME_SIZE)
- .webSocketCompression(true), createSSLOptions());
-
- assertTrue(transport instanceof WebSocketTransport);
-
- try {
- // Transport allows bigger frames in so that server is the one causing the failure.
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- transports.add(transport);
- transport.writeAndFlush(sendBuffer.copy());
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(Wait.waitFor(new Wait.Condition() {
- @Override
- public boolean isSatisfied() throws Exception {
- try {
- transport.writeAndFlush(sendBuffer.copy());
- } catch (IOException e) {
- LOG.info("Transport send caught error:", e);
- return false;
- }
-
- return true;
- }
- }, 10000, 10), "Transport should not have lost connection");
-
- transport.close();
- }
- }
-
- @Test
- public void testConfiguredHttpHeadersArriveAtServer() throws Exception {
- try (NettyEchoServer server = createEchoServer()) {
- server.start();
-
- final int port = server.getServerPort();
-
- TransportOptions clientOptions = createTransportOptions();
- clientOptions.addWebSocketHeader("test-header1", "FOO");
- clientOptions.webSocketHeaders().put("test-header2", "BAR");
-
- final Transport transport = createTransport(clientOptions, createSSLOptions());
-
- assertTrue(transport instanceof WebSocketTransport);
-
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- LOG.info("Connected to server:{}:{} as expected.", HOSTNAME, port);
- } catch (Exception e) {
- fail("Should have connected to the server at " + HOSTNAME + ":" + port + " but got exception: " + e);
- }
-
- assertTrue(transport.isConnected());
- assertEquals(HOSTNAME, transport.getHost(), "Server host is incorrect");
- assertEquals(port, transport.getPort(), "Server port is incorrect");
-
- assertTrue(server.awaitHandshakeCompletion(2000), "HandshakeCompletion not set within given time");
-
- WebSocketServerHandshakeCompletionEvent handshake = server.getHandshakeComplete();
- assertNotNull(handshake, "completion should not be null");
- HttpHeaders requestHeaders = handshake.requestHeaders();
-
- assertTrue(requestHeaders.contains("test-header1"));
- assertTrue(requestHeaders.contains("test-header2"));
-
- assertEquals("FOO", requestHeaders.get("test-header1"));
- assertEquals("BAR", requestHeaders.get("test-header2"));
-
- transport.close();
- }
-
- assertTrue(!transportErrored); // Normal shutdown does not trigger the event.
- assertTrue(exceptions.isEmpty());
- assertTrue(data.isEmpty());
- }
-
- private static final String BROKER_JKS_KEYSTORE = "src/test/resources/broker-jks.keystore";
- private static final String PASSWORD = "password";
-
- @Test
- public void testNonSslWebSocketConnectionFailsToSslServer() throws Exception {
- SslOptions serverSslOptions = new SslOptions();
- serverSslOptions.keyStoreLocation(BROKER_JKS_KEYSTORE);
- serverSslOptions.keyStorePassword(PASSWORD);
- serverSslOptions.verifyHost(false);
- serverSslOptions.sslEnabled(true);
-
- try (NettyBlackHoleServer server = new NettyBlackHoleServer(createServerTransportOptions(), serverSslOptions)) {
- server.start();
-
- final int port = server.getServerPort();
-
- TransportOptions clientOptions = createTransportOptions();
-
- final Transport transport = createTransport(clientOptions, createSSLOptions());
-
- assertTrue(transport instanceof WebSocketTransport);
-
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- fail("should not have connected");
- } catch (Exception e) {
- LOG.trace("Failed to connect with message: {}", e.getMessage());
- }
- }
- }
-
- @Test
- public void testWebsocketConnectionToBlackHoleServerTimesOut() throws Exception {
- try (NettyBlackHoleServer server = new NettyBlackHoleServer(new TransportOptions(), new SslOptions().sslEnabled(false))) {
- server.start();
-
- final int port = server.getServerPort();
-
- TransportOptions clientOptions = createTransportOptions();
- clientOptions.connectTimeout(25);
-
- final Transport transport = createTransport(clientOptions, createSSLOptions());
-
- assertTrue(transport instanceof WebSocketTransport);
-
- try {
- transport.connect(HOSTNAME, port, testListener).awaitConnect();
- fail("should not have connected");
- } catch (Exception e) {
- String message = e.getMessage();
- assertNotNull(message);
- assertTrue(message.contains("WebSocket handshake timed out"), "Unexpected message: " + message);
- }
- }
- }
-}
diff --git a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/X509AliasKeyManagerTest.java b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/X509AliasKeyManagerTest.java
deleted file mode 100644
index 3373422d..00000000
--- a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/transport/netty5/X509AliasKeyManagerTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.client.transport.netty5;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.net.Socket;
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.X509ExtendedKeyManager;
-
-import org.apache.qpid.protonj2.client.transport.X509AliasKeyManager;
-import org.junit.jupiter.api.Test;
-
-public class X509AliasKeyManagerTest {
-
- @Test
- public void testNullAliasCausesIAE() {
- try {
- new X509AliasKeyManager(null, mock(X509ExtendedKeyManager.class));
- fail("Expected an exception to be thrown");
- } catch (IllegalArgumentException iae) {
- // expected
- }
- }
-
- @Test
- public void testChooseClientAliasReturnsGivenAlias() {
- String wrapperAlias = "wrapperAlias";
- String myDelegateAlias = "delegateAlias";
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.chooseClientAlias(any(String[].class), any(Principal[].class), any(Socket.class))).thenReturn(myDelegateAlias);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertEquals(wrapperAlias, wrapper.chooseClientAlias(new String[0], new Principal[0], new Socket()), "Expected wrapper alias");
- }
-
- @Test
- public void testChooseServerAliasReturnsGivenAlias() {
- String wrapperAlias = "wrapperAlias";
- String myDelegateAlias = "delegateAlias";
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.chooseServerAlias(any(String.class), any(Principal[].class), any(Socket.class))).thenReturn(myDelegateAlias);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertEquals(wrapperAlias, wrapper.chooseServerAlias("", new Principal[0], new Socket()), "Expected wrapper alias");
- }
-
- @Test
- public void testGetCertificateChainDelegates() {
- String wrapperAlias = "wrapperAlias";
- X509Certificate[] certs = new X509Certificate[7];
-
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.getCertificateChain(any(String.class))).thenReturn(certs);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertSame(certs, wrapper.getCertificateChain(wrapperAlias), "Different object returned");
- }
-
- @Test
- public void testGetClientAliasesReturnsGivenAliasOnly() {
- String wrapperAlias = "wrapperAlias";
- String[] delegateAliases = new String[] { "a", "b", wrapperAlias};
-
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.getClientAliases(any(String.class), any(Principal[].class))).thenReturn(delegateAliases);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertArrayEquals(new String[] { wrapperAlias }, wrapper.getClientAliases("", new Principal[0]), "Expected array containing only the wrapper alias");
- }
-
- @Test
- public void testGetServerAliasesReturnsGivenAliasOnly() {
- String wrapperAlias = "wrapperAlias";
- String[] delegateAliases = new String[] { "a", "b", wrapperAlias};
-
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.getServerAliases(any(String.class), any(Principal[].class))).thenReturn(delegateAliases);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertArrayEquals(new String[] { wrapperAlias }, wrapper.getServerAliases("", new Principal[0]), "Expected array containing only the wrapper alias");
- }
-
- @Test
- public void testGetPrivateKeyDelegates() {
- String wrapperAlias = "wrapperAlias";
- PrivateKey mockKey = mock(PrivateKey.class);
-
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.getPrivateKey(any(String.class))).thenReturn(mockKey);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertSame(mockKey, wrapper.getPrivateKey(wrapperAlias), "Different object returned");
- }
-
- @Test
- public void testChooseEngineClientAliasReturnsGivenAlias() {
- String wrapperAlias = "wrapperAlias";
- String myDelegateAlias = "delegateAlias";
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.chooseEngineClientAlias(any(String[].class), any(Principal[].class), any(SSLEngine.class))).thenReturn(myDelegateAlias);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertEquals(wrapperAlias, wrapper.chooseEngineClientAlias(new String[0], new Principal[0], mock(SSLEngine.class)), "Expected wrapper alias");
- }
-
- @Test
- public void testChooseEngineServerAliasReturnsGivenAlias() {
- String wrapperAlias = "wrapperAlias";
- String myDelegateAlias = "delegateAlias";
- X509ExtendedKeyManager mock = mock(X509ExtendedKeyManager.class);
- when(mock.chooseEngineServerAlias(any(String.class), any(Principal[].class), any(SSLEngine.class))).thenReturn(myDelegateAlias);
-
- X509ExtendedKeyManager wrapper = new X509AliasKeyManager(wrapperAlias, mock);
-
- assertEquals(wrapperAlias, wrapper.chooseEngineServerAlias("", new Principal[0], mock(SSLEngine.class)), "Expected wrapper alias");
- }
-}
diff --git a/protonj2-test-driver/pom.xml b/protonj2-test-driver/pom.xml
index 5ab0a5e8..670de206 100644
--- a/protonj2-test-driver/pom.xml
+++ b/protonj2-test-driver/pom.xml
@@ -54,32 +54,6 @@
<artifactId>netty-codec-http</artifactId>
<scope>${netty-scope}</scope>
</dependency>
- <!-- Netty 5 Development dependencies -->
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-buffer</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-common</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-handler</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-transport</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-codec-http</artifactId>
- <scope>${netty5-scope}</scope>
- </dependency>
<!-- All other test peer dependencies -->
<dependency>
<groupId>org.slf4j</groupId>
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/NettyIOBuilder.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/NettyIOBuilder.java
index 39d77db9..29e306d0 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/NettyIOBuilder.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/NettyIOBuilder.java
@@ -25,9 +25,6 @@ import org.apache.qpid.protonj2.test.driver.ProtonTestServerOptions;
import org.apache.qpid.protonj2.test.driver.netty.netty4.Netty4Client;
import org.apache.qpid.protonj2.test.driver.netty.netty4.Netty4Server;
import org.apache.qpid.protonj2.test.driver.netty.netty4.Netty4Support;
-import org.apache.qpid.protonj2.test.driver.netty.netty5.Netty5Client;
-import org.apache.qpid.protonj2.test.driver.netty.netty5.Netty5Server;
-import org.apache.qpid.protonj2.test.driver.netty.netty5.Netty5Support;
/**
* An I/O context used to abstract the implementation of the IO layer in use.
@@ -49,8 +46,6 @@ public interface NettyIOBuilder {
public static NettyClient createClient(ProtonTestClientOptions options, Runnable connectedHandler, Consumer<ByteBuffer> inputHandler) {
if (Netty4Support.isAvailable()) {
return new Netty4Client(options, connectedHandler, inputHandler);
- } else if (Netty5Support.isAvailable()) {
- return new Netty5Client(options, connectedHandler, inputHandler);
}
throw new UnsupportedOperationException("Netty not available on the class path");
@@ -73,8 +68,6 @@ public interface NettyIOBuilder {
public static NettyServer createServer(ProtonTestServerOptions options, Runnable connectedHandler, Runnable disconnectedHandler, Consumer<ByteBuffer> inputHandler) {
if (Netty4Support.isAvailable()) {
return new Netty4Server(options, connectedHandler, disconnectedHandler, inputHandler);
- } else if (Netty5Support.isAvailable()) {
- return new Netty5Server(options, connectedHandler, disconnectedHandler, inputHandler);
}
throw new UnsupportedOperationException("Netty not available on the class path");
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Client.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Client.java
deleted file mode 100644
index b17209e2..00000000
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Client.java
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.test.driver.netty.netty5;
-
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
-import org.apache.qpid.protonj2.test.driver.ProtonTestClientOptions;
-import org.apache.qpid.protonj2.test.driver.netty.NettyClient;
-import org.apache.qpid.protonj2.test.driver.netty.NettyEventLoop;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.bootstrap.Bootstrap;
-import io.netty5.buffer.Buffer;
-import io.netty5.buffer.BufferAllocator;
-import io.netty5.channel.Channel;
-import io.netty5.channel.ChannelFutureListeners;
-import io.netty5.channel.ChannelHandler;
-import io.netty5.channel.ChannelHandlerAdapter;
-import io.netty5.channel.ChannelHandlerContext;
-import io.netty5.channel.ChannelInitializer;
-import io.netty5.channel.ChannelOption;
-import io.netty5.channel.EventLoop;
-import io.netty5.channel.EventLoopGroup;
-import io.netty5.channel.MultithreadEventLoopGroup;
-import io.netty5.channel.SimpleChannelInboundHandler;
-import io.netty5.channel.nio.NioHandler;
-import io.netty5.channel.socket.nio.NioSocketChannel;
-import io.netty5.handler.codec.http.DefaultHttpContent;
-import io.netty5.handler.codec.http.FullHttpRequest;
-import io.netty5.handler.codec.http.FullHttpResponse;
-import io.netty5.handler.codec.http.HttpClientCodec;
-import io.netty5.handler.codec.http.HttpObjectAggregator;
-import io.netty5.handler.codec.http.headers.HttpHeaders;
-import io.netty5.handler.codec.http.websocketx.BinaryWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.CloseWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.ContinuationWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.PingWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.PongWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.TextWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketClientHandshaker;
-import io.netty5.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
-import io.netty5.handler.codec.http.websocketx.WebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketVersion;
-import io.netty5.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
-import io.netty5.handler.logging.LoggingHandler;
-import io.netty5.handler.ssl.SslHandler;
-import io.netty5.util.concurrent.Future;
-import io.netty5.util.concurrent.FutureListener;
-
-/**
- * Self contained Netty client implementation that provides a base for more
- * complex client implementations to use as the IO layer.
- */
-public final class Netty5Client implements NettyClient {
-
- private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private static final String AMQP_SUB_PROTOCOL = "amqp";
- private static final int SHUTDOWN_TIMEOUT = 50;
-
- private Netty5EventLoop eventLoop;
- private Bootstrap bootstrap;
- private EventLoopGroup group;
- private Channel channel;
- private String host;
- private int port;
- private boolean wsCompressionRequest;
- private boolean wsCompressionResponse;
- protected volatile IOException failureCause;
- private final ProtonTestClientOptions options;
- private volatile SslHandler sslHandler;
- protected final AtomicBoolean connected = new AtomicBoolean();
- protected final AtomicBoolean closed = new AtomicBoolean();
- protected final CountDownLatch connectedLatch = new CountDownLatch(1);
-
- private final Consumer<ByteBuffer> inputConsumer;
- private final Runnable connectedRunnable;
-
- public Netty5Client(ProtonTestClientOptions options, Runnable connectedRunnable, Consumer<ByteBuffer> inputConsumer) {
- Objects.requireNonNull(options);
- Objects.requireNonNull(inputConsumer);
- Objects.requireNonNull(connectedRunnable);
-
- this.options = options;
- this.connectedRunnable = connectedRunnable;
- this.inputConsumer = inputConsumer;
- }
-
- @Override
- public void close() throws Exception {
- if (closed.compareAndSet(false, true)) {
- connected.set(false);
- connectedLatch.countDown();
- if (channel != null) {
- try {
- if (!channel.close().asStage().await(10, TimeUnit.SECONDS)) {
- LOG.info("Channel close timed out waiting for result");
- }
- } catch (InterruptedException e) {
- Thread.interrupted();
- LOG.debug("Close of channel interrupted while awaiting result");
- }
- }
-
- if (group != null && !group.isShutdown()) {
- group.shutdownGracefully(0, SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
- try {
- if (eventLoop != null && eventLoop.inEventLoop()) {
- // If scripted close we might be inside the event loop and
- // we cannot wait in that case.
- return;
- }
-
- if (!group.awaitTermination(2 * SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS)) {
- LOG.trace("Connection IO Event Loop shutdown failed to complete in allotted time");
- }
- } catch (InterruptedException e) {
- Thread.interrupted();
- LOG.debug("Shutdown of netty event loop interrupted while awaiting result");
- }
- }
- }
- }
-
- @Override
- public void connect(String host, int port) throws IOException {
- if (closed.get()) {
- throw new IllegalStateException("Netty client has already been closed");
- }
-
- if (host == null || host.isEmpty()) {
- throw new IllegalArgumentException("Transport host value cannot be null");
- }
-
- this.host = host;
-
- if (port > 0) {
- this.port = port;
- } else {
- if (options.isSecure()) {
- this.port = ProtonTestClientOptions.DEFAULT_SSL_PORT;
- } else {
- this.port = ProtonTestClientOptions.DEFAULT_TCP_PORT;
- }
- }
-
- group = new MultithreadEventLoopGroup(1, NioHandler.newFactory());
- bootstrap = new Bootstrap().channel(NioSocketChannel.class).group(group);
- bootstrap.handler(new ChannelInitializer<Channel>() {
- @Override
- public void initChannel(Channel transportChannel) throws Exception {
- channel = transportChannel;
- eventLoop = new Netty5EventLoop(channel.executor());
- configureChannel(transportChannel);
- }
- });
-
- configureNetty(bootstrap, options);
-
- bootstrap.connect(host, port).addListener(channel, ChannelFutureListeners.FIRE_EXCEPTION_ON_FAILURE);
- try {
- connectedLatch.await();
- } catch (InterruptedException e) {
- Thread.interrupted();
- }
-
- if (!connected.get()) {
- if (failureCause != null) {
- throw failureCause;
- } else {
- throw new IOException("Netty client was closed before a connection was established.");
- }
- }
- }
-
- @Override
- public NettyEventLoop eventLoop() {
- if (channel == null || !channel.isActive()) {
- throw new IllegalStateException("Channel is not connected or has closed");
- }
-
- return eventLoop;
- }
-
- @Override
- public void write(ByteBuffer buffer) {
- if (channel == null || !channel.isActive()) {
- throw new IllegalStateException("Channel is not connected or has closed");
- }
-
- channel.writeAndFlush(BufferAllocator.onHeapUnpooled().copyOf(buffer).makeReadOnly());
- }
-
- @Override
- public boolean isConnected() {
- return connected.get();
- }
-
- @Override
- public boolean isSecure() {
- return options.isSecure();
- }
-
- @Override
- public boolean isWSCompressionActive() {
- if (channel == null || !channel.isActive()) {
- throw new IllegalStateException("Channel is not connected or has closed");
- }
-
- return wsCompressionRequest && wsCompressionResponse;
- }
-
- @Override
- public URI getRemoteURI() {
- if (host != null) {
- try {
- if (options.isUseWebSockets()) {
- return new URI(options.isSecure() ? "wss" : "ws", null, host, port, options.getWebSocketPath(), null, null);
- } else {
- return new URI(options.isSecure() ? "ssl" : "tcp", null, host, port, null, null, null);
- }
- } catch (URISyntaxException e) {
- }
- }
-
- return null;
- }
-
- //----- Default implementation of Netty handler
-
- protected class NettyClientInboundHandler implements ChannelHandler {
-
- private final WebSocketClientHandshaker handshaker;
- private Future<Void> handshakeTimeoutFuture;
-
- public NettyClientInboundHandler() {
- if (options.isUseWebSockets()) {
- HttpHeaders headers = HttpHeaders.newHeaders();
-
- options.getHttpHeaders().forEach((key, value) -> {
- headers.set(key, value);
- });
-
- handshaker = WebSocketClientHandshakerFactory.newHandshaker(
- getRemoteURI(), WebSocketVersion.V13, AMQP_SUB_PROTOCOL,
- true, headers, options.getWebSocketMaxFrameSize());
- } else {
- handshaker = null;
- }
- }
-
- @Override
- public final void channelRegistered(ChannelHandlerContext context) throws Exception {
- channel = context.channel();
- }
-
- @Override
- public void channelActive(ChannelHandlerContext context) throws Exception {
- if (options.isUseWebSockets()) {
- handshaker.handshake(context.channel());
-
- handshakeTimeoutFuture = context.executor().schedule(()-> {
- LOG.trace("WebSocket handshake timed out! Channel is {}", context.channel());
- if (!handshaker.isHandshakeComplete()) {
- Netty5Client.this.handleTransportFailure(channel, new IOException("WebSocket handshake timed out"));
- }
- }, options.getConnectTimeout(), TimeUnit.MILLISECONDS);
- }
-
- // In the Secure case we need to let the handshake complete before we
- // trigger the connected event.
- if (!isSecure()) {
- if (!options.isUseWebSockets()) {
- handleConnected(context.channel());
- }
- } else {
- SslHandler sslHandler = context.pipeline().get(SslHandler.class);
- sslHandler.handshakeFuture().addListener(new FutureListener<Channel>() {
- @Override
- public void operationComplete(Future<? extends Channel> future) throws Exception {
- if (future.isSuccess()) {
- LOG.trace("SSL Handshake has completed: {}", channel);
- if (!options.isUseWebSockets()) {
- handleConnected(channel);
- }
- } else {
- LOG.trace("SSL Handshake has failed: {}", channel);
- handleTransportFailure(channel, future.cause());
- }
- }
- });
- }
- }
-
- @Override
- public void channelInactive(ChannelHandlerContext context) throws Exception {
- if (handshakeTimeoutFuture != null) {
- handshakeTimeoutFuture.cancel();
- }
-
- handleTransportFailure(context.channel(), new IOException("Remote closed connection unexpectedly"));
- }
-
- @Override
- public void channelExceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
- handleTransportFailure(context.channel(), cause);
- }
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object message) {
- if (options.isUseWebSockets()) {
- LOG.trace("New data read: incoming: {}", message);
-
- Channel ch = ctx.channel();
- if (!handshaker.isHandshakeComplete()) {
- handshaker.finishHandshake(ch, (FullHttpResponse) message);
- LOG.trace("WebSocket Client connected! {}", ctx.channel());
- // Now trigger super processing as we are really connected.
- if (handshakeTimeoutFuture.cancel()) {
- handleConnected(ch);
- }
-
- return;
- }
-
- // We shouldn't get this since we handle the handshake previously.
- if (message instanceof FullHttpResponse) {
- FullHttpResponse response = (FullHttpResponse) message;
- throw new IllegalStateException(
- "Unexpected FullHttpResponse (getStatus=" + response.status() +
- ", content=" + response.payload().toString(StandardCharsets.UTF_8) + ')');
- }
-
- WebSocketFrame frame = (WebSocketFrame) message;
- if (frame instanceof TextWebSocketFrame) {
- TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
- LOG.warn("WebSocket Client received message: " + textFrame.text());
- ctx.fireChannelExceptionCaught(new IOException("Received invalid frame over WebSocket."));
- } else if (frame instanceof BinaryWebSocketFrame) {
- BinaryWebSocketFrame binaryFrame = (BinaryWebSocketFrame) frame;
- LOG.trace("WebSocket Client received data: {} bytes", binaryFrame.binaryData().readableBytes());
- ctx.fireChannelRead(binaryFrame.binaryData());
- } else if (frame instanceof ContinuationWebSocketFrame) {
- ContinuationWebSocketFrame continuationFrame = (ContinuationWebSocketFrame) frame;
- LOG.trace("WebSocket Client received data continuation: {} bytes", continuationFrame.binaryData().readableBytes());
- ctx.fireChannelRead(continuationFrame.binaryData());
- } else if (frame instanceof PingWebSocketFrame) {
- LOG.trace("WebSocket Client received ping, response with pong");
- ch.write(new PongWebSocketFrame(frame.binaryData()));
- } else if (frame instanceof CloseWebSocketFrame) {
- LOG.trace("WebSocket Client received closing");
- ch.close();
- }
- } else {
- ctx.fireChannelRead(message);
- }
- }
- }
-
- private class NettyClientOutboundHandler extends ChannelHandlerAdapter {
-
- @Override
- public Future<Void> write(ChannelHandlerContext ctx, Object msg) {
- LOG.trace("NettyServerHandler: Channel write: {}", msg);
- if (options.isUseWebSockets() && msg instanceof Buffer) {
- if (options.isFragmentWrites()) {
- Buffer orig = (Buffer) msg;
- int origIndex = orig.readerOffset();
- int split = orig.readableBytes()/2;
-
- Buffer part1 = orig.copy(origIndex, split);
- LOG.trace("NettyClientOutboundHandler: Part1: {}", part1);
- orig.readerOffset(origIndex + split);
- LOG.trace("NettyClientOutboundHandler: Part2: {}", orig);
-
- BinaryWebSocketFrame frame1 = new BinaryWebSocketFrame(false, 0, part1);
- ctx.writeAndFlush(frame1);
- ContinuationWebSocketFrame frame2 = new ContinuationWebSocketFrame(true, 0, orig);
- return ctx.write(frame2);
- } else {
- BinaryWebSocketFrame frame = new BinaryWebSocketFrame((Buffer) msg);
- return ctx.write(frame);
- }
- } else {
- return ctx.write(msg);
- }
- }
- }
-
- private class ClientWSCompressionObserverHandler extends ChannelHandlerAdapter {
-
- final String WS_EXTENSIONS_SECTION = "sec-websocket-extensions";
- final String WS_PERMESSAGE_DEFLATE = "permessage-deflate";
- final String WS_UPGRADE = "upgrade";
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object message) {
- if (message instanceof FullHttpResponse) {
- FullHttpResponse response = (FullHttpResponse) message;
- HttpHeaders headers = response.headers();
-
- if (headers.contains(WS_UPGRADE) && headers.contains(WS_EXTENSIONS_SECTION)) {
- wsCompressionRequest = headers.get(WS_EXTENSIONS_SECTION).toString().contains(WS_PERMESSAGE_DEFLATE);
- }
- }
-
- ctx.fireChannelRead(message);
- }
-
- @Override
- public Future<Void> write(ChannelHandlerContext context, Object message) {
- if (message instanceof FullHttpRequest) {
- FullHttpRequest request = (FullHttpRequest) message;
- HttpHeaders headers = request.headers();
-
- if (headers.contains(WS_UPGRADE) && headers.contains(WS_EXTENSIONS_SECTION)) {
- wsCompressionRequest = headers.get(WS_EXTENSIONS_SECTION).toString().contains(WS_PERMESSAGE_DEFLATE);
- }
- }
-
- return context.write(message);
- }
- }
-
- //----- Internal Client implementation API
-
- protected ChannelHandler getClientHandler() {
- return new SimpleChannelInboundHandler<Buffer>() {
-
- @Override
- protected void messageReceived(ChannelHandlerContext ctx, Buffer input) throws Exception {
- LOG.trace("AMQP Test Client Channel read: {}", input);
-
- // Driver processes new data and may produce output based on this.
- try {
- final ByteBuffer copy = ByteBuffer.allocate(input.readableBytes());
- input.readBytes(copy);
- inputConsumer.accept(copy.flip().asReadOnlyBuffer());
- } catch (Throwable e) {
- LOG.error("Closed AMQP Test client channel due to error: ", e);
- ctx.channel().close();
- }
- }
- };
- }
-
- protected EventLoop getEventLoop() {
- if (channel == null || !channel.isActive()) {
- throw new IllegalStateException("Channel is not connected or has closed");
- }
-
- return channel.executor();
- }
-
- protected SslHandler getSslHandler() {
- return sslHandler;
- }
-
- private void configureChannel(final Channel channel) throws Exception {
- if (isSecure()) {
- final SslHandler sslHandler;
- try {
- sslHandler = SslSupport.createClientSslHandler(getRemoteURI(), options);
- } catch (Exception ex) {
- LOG.warn("Error during initialization of channel from SSL Handler creation:");
- handleTransportFailure(channel, ex);
- throw new IOException(ex);
- }
-
- channel.pipeline().addLast("ssl", sslHandler);
- }
-
- if (options.isTraceBytes()) {
- channel.pipeline().addLast("logger", new LoggingHandler(getClass()));
- }
-
- if (options.isUseWebSockets()) {
- channel.pipeline().addLast(new HttpClientCodec());
- channel.pipeline().addLast(new HttpObjectAggregator<DefaultHttpContent>(8192));
- if (options.isWebSocketCompression()) {
- channel.pipeline().addLast(new ClientWSCompressionObserverHandler());
- channel.pipeline().addLast(WebSocketClientCompressionHandler.INSTANCE);
- }
- }
-
- channel.pipeline().addLast(new NettyClientOutboundHandler());
- channel.pipeline().addLast(new NettyClientInboundHandler());
- channel.pipeline().addLast(getClientHandler());
- }
-
- private void configureNetty(Bootstrap bootstrap, ProtonTestClientOptions options) {
- bootstrap.option(ChannelOption.TCP_NODELAY, options.isTcpNoDelay());
- bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, options.getConnectTimeout());
- bootstrap.option(ChannelOption.SO_KEEPALIVE, options.isTcpKeepAlive());
- bootstrap.option(ChannelOption.SO_LINGER, options.getSoLinger());
-
- if (options.getSendBufferSize() != -1) {
- bootstrap.option(ChannelOption.SO_SNDBUF, options.getSendBufferSize());
- }
-
- if (options.getReceiveBufferSize() != -1) {
- bootstrap.option(ChannelOption.SO_RCVBUF, options.getReceiveBufferSize());
- }
-
- if (options.getTrafficClass() != -1) {
- bootstrap.option(ChannelOption.IP_TOS, options.getTrafficClass());
- }
-
- if (options.getLocalAddress() != null || options.getLocalPort() != 0) {
- if (options.getLocalAddress() != null) {
- bootstrap.localAddress(options.getLocalAddress(), options.getLocalPort());
- } else {
- bootstrap.localAddress(options.getLocalPort());
- }
- }
- }
-
- //----- Event Handlers which can be overridden in subclasses -------------//
-
- protected void handleConnected(Channel connectedChannel) {
- LOG.trace("Channel has become active! Channel is {}", connectedChannel);
- channel = connectedChannel;
- connected.set(true);
- connectedLatch.countDown();
- connectedRunnable.run();
- }
-
- protected void handleTransportFailure(Channel failedChannel, Throwable cause) {
- if (!closed.get()) {
- LOG.trace("Channel indicates connection failure! Channel is {}", failedChannel);
- failureCause = new IOException(cause);
- channel = failedChannel;
- connected.set(false);
- connectedLatch.countDown();
- } else {
- LOG.trace("Closed Channel signalled that the channel ended: {}", channel);
- }
- }
-}
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5EventLoop.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5EventLoop.java
deleted file mode 100644
index 16056003..00000000
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5EventLoop.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.qpid.protonj2.test.driver.netty.netty5;
-
-import java.util.concurrent.TimeUnit;
-
-import org.apache.qpid.protonj2.test.driver.netty.NettyEventLoop;
-
-import io.netty5.channel.EventLoop;
-
-public final class Netty5EventLoop implements NettyEventLoop {
-
- private final EventLoop loop;
-
- public Netty5EventLoop(EventLoop loop) {
- this.loop = loop;
- }
-
- @Override
- public boolean inEventLoop() {
- return loop.inEventLoop();
- }
-
- @Override
- public void execute(Runnable runnable) {
- loop.execute(runnable);
- }
-
- @Override
- public void schedule(Runnable runnable, int delay, TimeUnit unit) {
- loop.schedule(runnable, delay, unit);
- }
-}
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Server.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Server.java
deleted file mode 100644
index 4e08ba49..00000000
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Server.java
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.test.driver.netty.netty5;
-
-import java.lang.invoke.MethodHandles;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLPeerUnverifiedException;
-
-import org.apache.qpid.protonj2.test.driver.ProtonTestServerOptions;
-import org.apache.qpid.protonj2.test.driver.netty.NettyEventLoop;
-import org.apache.qpid.protonj2.test.driver.netty.NettyServer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.bootstrap.ServerBootstrap;
-import io.netty5.buffer.Buffer;
-import io.netty5.buffer.BufferAllocator;
-import io.netty5.buffer.DefaultBufferAllocators;
-import io.netty5.channel.Channel;
-import io.netty5.channel.ChannelFutureListeners;
-import io.netty5.channel.ChannelHandler;
-import io.netty5.channel.ChannelHandlerAdapter;
-import io.netty5.channel.ChannelHandlerContext;
-import io.netty5.channel.ChannelInitializer;
-import io.netty5.channel.ChannelOption;
-import io.netty5.channel.EventLoopGroup;
-import io.netty5.channel.MultithreadEventLoopGroup;
-import io.netty5.channel.SimpleChannelInboundHandler;
-import io.netty5.channel.nio.NioHandler;
-import io.netty5.channel.socket.nio.NioServerSocketChannel;
-import io.netty5.handler.codec.http.DefaultFullHttpResponse;
-import io.netty5.handler.codec.http.DefaultHttpContent;
-import io.netty5.handler.codec.http.FullHttpRequest;
-import io.netty5.handler.codec.http.FullHttpResponse;
-import io.netty5.handler.codec.http.HttpObjectAggregator;
-import io.netty5.handler.codec.http.HttpResponseStatus;
-import io.netty5.handler.codec.http.HttpServerCodec;
-import io.netty5.handler.codec.http.HttpUtil;
-import io.netty5.handler.codec.http.HttpVersion;
-import io.netty5.handler.codec.http.headers.HttpHeaders;
-import io.netty5.handler.codec.http.websocketx.BinaryWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.ContinuationWebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketFrame;
-import io.netty5.handler.codec.http.websocketx.WebSocketServerHandshakeCompletionEvent;
-import io.netty5.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
-import io.netty5.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
-import io.netty5.handler.logging.LogLevel;
-import io.netty5.handler.logging.LoggingHandler;
-import io.netty5.handler.ssl.SslHandler;
-import io.netty5.util.concurrent.Future;
-import io.netty5.util.concurrent.FutureListener;
-
-/**
- * Base Server implementation used to create Netty based server implementations for
- * unit testing aspects of the client code.
- */
-public final class Netty5Server implements NettyServer {
-
- private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- static final int PORT = Integer.parseInt(System.getProperty("port", "5672"));
- static final String WEBSOCKET_PATH = "/";
- static final int DEFAULT_MAX_FRAME_SIZE = 65535;
-
- private Netty5EventLoop eventLoop;
- private EventLoopGroup bossGroup;
- private EventLoopGroup workerGroup;
- private Channel serverChannel;
- private Channel clientChannel;
- private final ProtonTestServerOptions options;
- private int maxFrameSize = DEFAULT_MAX_FRAME_SIZE;
- private String webSocketPath = WEBSOCKET_PATH;
- private boolean wsCompressionRequest;
- private boolean wsCompressionResponse;
- private volatile SslHandler sslHandler;
- private volatile WebSocketServerHandshakeCompletionEvent handshakeComplete;
- private final CountDownLatch handshakeCompletion = new CountDownLatch(1);
-
- private final AtomicBoolean started = new AtomicBoolean();
-
- private final Consumer<ByteBuffer> inputConsumer;
- private final Runnable connectedRunnable;
- private final Runnable disconnectedRunnable;
-
- public Netty5Server(ProtonTestServerOptions options, Runnable connectedRunnable, Runnable disconnectedRunnable, Consumer<ByteBuffer> inputConsumer) {
- Objects.requireNonNull(options);
- Objects.requireNonNull(inputConsumer);
- Objects.requireNonNull(connectedRunnable);
-
- this.options = options;
- this.connectedRunnable = connectedRunnable;
- this.disconnectedRunnable = disconnectedRunnable;
- this.inputConsumer = inputConsumer;
- }
-
- @Override
- public boolean isSecureServer() {
- return options.isSecure();
- }
-
- @Override
- public boolean isAcceptingConnections() {
- return serverChannel != null && serverChannel.isOpen();
- }
-
- @Override
- public boolean hasSecureConnection() {
- return sslHandler != null;
- }
-
- @Override
- public boolean hasClientConnection() {
- return clientChannel != null && clientChannel.isOpen();
- }
-
- @Override
- public int getClientPort() {
- Objects.requireNonNull(clientChannel);
- return (((InetSocketAddress) clientChannel.remoteAddress()).getPort());
- }
-
- @Override
- public boolean isWSCompressionActive() {
- Objects.requireNonNull(clientChannel);
- return wsCompressionRequest && wsCompressionResponse;
- }
-
- @Override
- public boolean isPeerVerified() {
- try {
- if (hasSecureConnection()) {
- return sslHandler.engine().getSession().getPeerPrincipal() != null;
- } else {
- return false;
- }
- } catch (SSLPeerUnverifiedException unverified) {
- return false;
- }
- }
-
- @Override
- public SSLEngine getConnectionSSLEngine() {
- if (hasSecureConnection()) {
- return sslHandler.engine();
- } else {
- return null;
- }
- }
-
- @Override
- public boolean isWebSocketServer() {
- return options.isUseWebSockets();
- }
-
- @Override
- public String getWebSocketPath() {
- return webSocketPath;
- }
-
- @Override
- public void setWebSocketPath(String webSocketPath) {
- this.webSocketPath = webSocketPath;
- }
-
- @Override
- public int getMaxFrameSize() {
- return maxFrameSize;
- }
-
- @Override
- public void setMaxFrameSize(int maxFrameSize) {
- this.maxFrameSize = maxFrameSize;
- }
-
- public boolean awaitHandshakeCompletion(long delayMs) throws InterruptedException {
- return handshakeCompletion.await(delayMs, TimeUnit.MILLISECONDS);
- }
-
- public WebSocketServerHandshakeCompletionEvent getHandshakeComplete() {
- return handshakeComplete;
- }
-
- @Override
- public URI getConnectionURI(String queryString) throws Exception {
- if (!started.get()) {
- throw new IllegalStateException("Cannot get URI of non-started server");
- }
-
- int port = getServerPort();
-
- String scheme;
- String path;
-
- if (isWebSocketServer()) {
- if (isSecureServer()) {
- scheme = "amqpwss";
- } else {
- scheme = "amqpws";
- }
- } else {
- if (isSecureServer()) {
- scheme = "amqps";
- } else {
- scheme = "amqp";
- }
- }
-
- if (isWebSocketServer()) {
- path = getWebSocketPath();
- } else {
- path = null;
- }
-
- if (queryString != null && queryString.startsWith("?")) {
- queryString = queryString.substring(1);
- }
-
- return new URI(scheme, null, "localhost", port, path, queryString, null);
- }
-
- @Override
- public void start() throws Exception {
- if (started.compareAndSet(false, true)) {
- // Configure the server to basic NIO type channels
- bossGroup = new MultithreadEventLoopGroup(1, NioHandler.newFactory());
- workerGroup = new MultithreadEventLoopGroup(NioHandler.newFactory());
-
- ServerBootstrap server = new ServerBootstrap();
- server.group(bossGroup, workerGroup);
- server.channel(NioServerSocketChannel.class);
- server.option(ChannelOption.SO_BACKLOG, 100);
- server.handler(new LoggingHandler(LogLevel.INFO));
- server.childHandler(new ChannelInitializer<Channel>() {
-
- @Override
- public void initChannel(Channel ch) throws Exception {
- // Don't accept any new connections.
- serverChannel.close();
- // Now we know who the client is
- clientChannel = ch;
- eventLoop = new Netty5EventLoop(ch.executor());
-
- if (isSecureServer()) {
- ch.pipeline().addLast(sslHandler = SslSupport.createServerSslHandler(null, options));
- }
-
- if (options.isUseWebSockets()) {
- ch.pipeline().addLast(new HttpServerCodec());
- ch.pipeline().addLast(new HttpObjectAggregator<DefaultHttpContent>(65536));
- if (options.isWebSocketCompression()) {
- ch.pipeline().addLast(new ServerWSCompressionObserverHandler());
- ch.pipeline().addLast(new WebSocketServerCompressionHandler());
- }
- ch.pipeline().addLast(new WebSocketServerProtocolHandler(getWebSocketPath(), "amqp", true, maxFrameSize));
- }
-
- ch.pipeline().addLast(new NettyServerOutboundHandler());
- ch.pipeline().addLast(new NettyServerInboundHandler());
- ch.pipeline().addLast(getServerHandler());
- }
- });
-
- // Start the server and then update the server port in case the configuration
- // was such that the server chose a free port.
- serverChannel = server.bind(options.getServerPort()).asStage().get();
- options.setServerPort(((InetSocketAddress) serverChannel.localAddress()).getPort());
- }
- }
-
- protected ChannelHandler getServerHandler() {
- return new SimpleChannelInboundHandler<Buffer>() {
-
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- connectedRunnable.run();
- ctx.fireChannelActive();
- }
-
- @Override
- public void channelInactive(ChannelHandlerContext ctx) throws Exception {
- disconnectedRunnable.run();
- ctx.fireChannelInactive();
- }
-
- @Override
- protected void messageReceived(ChannelHandlerContext ctx, Buffer input) throws Exception {
- LOG.trace("AMQP Test Server Channel read: {}", input);
-
- // Driver processes new data and may produce output based on this.
- try {
- final ByteBuffer copy = ByteBuffer.allocate(input.readableBytes());
- input.readBytes(copy);
- inputConsumer.accept(copy.flip().asReadOnlyBuffer());
- } catch (Throwable e) {
- LOG.error("Closed AMQP Test server channel due to error: ", e);
- ctx.channel().close();
- }
- }
- };
- }
-
- @Override
- public void write(ByteBuffer frame) {
- if (clientChannel == null || !clientChannel.isActive()) {
- throw new IllegalStateException("Channel is not connected or has closed");
- }
-
- clientChannel.writeAndFlush(BufferAllocator.onHeapUnpooled().copyOf(frame).makeReadOnly());
- }
-
- @Override
- public NettyEventLoop eventLoop() {
- if (clientChannel == null || !clientChannel.isActive()) {
- throw new IllegalStateException("Channel is not connected or has closed");
- }
-
- return eventLoop;
- }
-
- @Override
- public void stop() throws InterruptedException {
- if (started.compareAndSet(true, false)) {
- LOG.info("Syncing channel close");
- serverChannel.close().asStage().sync();
-
- if (clientChannel != null) {
- try {
- if (!clientChannel.close().asStage().await(10, TimeUnit.SECONDS)) {
- LOG.info("Connected Client channel close timed out waiting for result");
- }
- } catch (InterruptedException e) {
- Thread.interrupted();
- LOG.debug("Close of connected client channel interrupted while awaiting result");
- }
- }
-
- // Shut down all event loops to terminate all threads.
- int timeout = 100;
- LOG.trace("Shutting down boss group");
- bossGroup.shutdownGracefully(0, timeout, TimeUnit.MILLISECONDS).asStage().await(timeout, TimeUnit.MILLISECONDS);
- LOG.trace("Boss group shut down");
-
- LOG.trace("Shutting down worker group");
- workerGroup.shutdownGracefully(0, timeout, TimeUnit.MILLISECONDS).asStage().await(timeout, TimeUnit.MILLISECONDS);
- LOG.trace("Worker group shut down");
- }
- }
-
- @Override
- public void stopAsync() throws InterruptedException {
- if (started.compareAndSet(true, false)) {
- LOG.info("Closing channel asynchronously");
- serverChannel.close().asStage().sync();
-
- if (clientChannel != null) {
- clientChannel.close();
- }
-
- // Shut down all event loops to terminate all threads.
- int timeout = 100;
- LOG.trace("Shutting down boss group asynchronously");
- bossGroup.shutdownGracefully(0, timeout, TimeUnit.MILLISECONDS);
-
- LOG.trace("Shutting down worker group asynchronously");
- workerGroup.shutdownGracefully(0, timeout, TimeUnit.MILLISECONDS);
- }
- }
-
- @Override
- public void close() throws InterruptedException {
- stop();
- }
-
- @Override
- public void disconnectClient() throws Exception {
- if (!started.get() || !serverChannel.isOpen()) {
- throw new IllegalStateException("Server must be currently active in order to reset");
- }
-
- if (clientChannel != null) {
- try {
- if (!clientChannel.close().asStage().await(10, TimeUnit.SECONDS)) {
- LOG.info("Connected Client channel close timed out waiting for result");
- }
- } catch (InterruptedException e) {
- Thread.interrupted();
- LOG.debug("Close of connected client channel interrupted while awaiting result");
- } finally {
- clientChannel = null;
- }
- }
- }
-
- @Override
- public int getServerPort() {
- if (!started.get()) {
- throw new IllegalStateException("Cannot get server port of non-started server");
- }
-
- return options.getServerPort();
- }
-
- private class NettyServerOutboundHandler extends ChannelHandlerAdapter {
-
- @Override
- public Future<Void> write(ChannelHandlerContext ctx, Object msg) {
- LOG.trace("NettyServerHandler: Channel write: {}", msg);
- if (isWebSocketServer() && msg instanceof Buffer) {
- if (options.isFragmentWrites()) {
- Buffer orig = (Buffer) msg;
- int origIndex = orig.readerOffset();
- int split = orig.readableBytes()/2;
-
- Buffer part1 = orig.copy(origIndex, split);
- LOG.trace("NettyServerHandler: Part1: {}", part1);
- orig.readerOffset(origIndex + split);
- LOG.trace("NettyServerHandler: Part2: {}", orig);
-
- BinaryWebSocketFrame frame1 = new BinaryWebSocketFrame(false, 0, part1);
- ctx.writeAndFlush(frame1);
- ContinuationWebSocketFrame frame2 = new ContinuationWebSocketFrame(true, 0, orig);
- return ctx.write(frame2);
- } else {
- BinaryWebSocketFrame frame = new BinaryWebSocketFrame((Buffer) msg);
- return ctx.write(frame);
- }
- } else {
- return ctx.write(msg);
- }
- }
- }
-
- private class NettyServerInboundHandler extends ChannelHandlerAdapter {
-
- @Override
- public void channelInboundEvent(ChannelHandlerContext context, Object payload) {
- if (payload instanceof WebSocketServerHandshakeCompletionEvent) {
- handshakeComplete = (WebSocketServerHandshakeCompletionEvent) payload;
- handshakeCompletion.countDown();
- }
- }
-
- @Override
- public void channelActive(final ChannelHandlerContext ctx) {
- LOG.info("NettyServerHandler -> New active channel: {}", ctx.channel());
- SslHandler handler = ctx.pipeline().get(SslHandler.class);
- if (handler != null) {
- handler.handshakeFuture().addListener(new FutureListener<Channel>() {
- @Override
- public void operationComplete(Future<? extends Channel> future) throws Exception {
- LOG.info("Server -> SSL handshake completed. Succeeded: {}", future.isSuccess());
- if (!future.isSuccess()) {
- ctx.close();
- }
- }
- });
- }
-
- ctx.fireChannelActive();
- }
-
- @Override
- public void channelInactive(ChannelHandlerContext ctx) throws Exception {
- LOG.info("NettyServerHandler: channel has gone inactive: {}", ctx.channel());
- ctx.close();
- ctx.fireChannelInactive();
- Netty5Server.this.clientChannel = null;
- }
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) {
- LOG.trace("NettyServerHandler: Channel read: {}", msg);
- if (msg instanceof WebSocketFrame) {
- WebSocketFrame frame = (WebSocketFrame) msg;
- ctx.fireChannelRead(frame.binaryData());
- } else if (msg instanceof FullHttpRequest) {
- // Reject anything not on the WebSocket path
- FullHttpRequest request = (FullHttpRequest) msg;
-
- sendHttpResponse(ctx, request,
- new DefaultFullHttpResponse(
- HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST, DefaultBufferAllocators.onHeapAllocator().allocate(0)));
- } else {
- // Forward anything else along to the next handler.
- ctx.fireChannelRead(msg);
- }
- }
-
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) {
- ctx.flush();
- }
-
- @Override
- public void channelExceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
- LOG.info("NettyServerHandler: NettyServerHandlerException caught on channel: {}", ctx.channel());
- // Close the connection when an exception is raised.
- cause.printStackTrace();
- ctx.close();
- }
- }
-
- private class ServerWSCompressionObserverHandler extends ChannelHandlerAdapter {
-
- final String WS_EXTENSIONS_SECTION = "sec-websocket-extensions";
- final String WS_PERMESSAGE_DEFLATE = "permessage-deflate";
- final String WS_UPGRADE = "upgrade";
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object message) {
- if (message instanceof FullHttpRequest) {
- FullHttpRequest request = (FullHttpRequest) message;
- HttpHeaders headers = request.headers();
-
- if (headers.contains(WS_UPGRADE) && headers.contains(WS_EXTENSIONS_SECTION)) {
- wsCompressionRequest = headers.get(WS_EXTENSIONS_SECTION).toString().contains(WS_PERMESSAGE_DEFLATE);
- }
- }
-
- ctx.fireChannelRead(message);
- }
-
- @Override
- public Future<Void> write(ChannelHandlerContext context, Object message) {
- if (message instanceof FullHttpResponse) {
- FullHttpResponse response = (FullHttpResponse) message;
- HttpHeaders headers = response.headers();
-
- if (headers.contains(WS_UPGRADE) && headers.contains(WS_EXTENSIONS_SECTION)) {
- wsCompressionResponse = headers.get(WS_EXTENSIONS_SECTION).toString().contains(WS_PERMESSAGE_DEFLATE);
- }
- }
-
- return context.write(message);
- }
- }
-
- private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response) {
- // Generate an error page if response getStatus code is not OK (200).
- if (response.status().code() != 200) {
- byte[] status = response.status().toString().getBytes(StandardCharsets.UTF_8);
- response.payload().writeBytes(status);
- HttpUtil.setContentLength(response, response.payload().readableBytes());
- }
-
- // Send the response and close the connection if necessary.
- Future<Void> f = ctx.channel().writeAndFlush(response);
- if (!HttpUtil.isKeepAlive(request) || response.status().code() != 200) {
- f.addListener(ctx.channel(), ChannelFutureListeners.CLOSE);
- }
- }
-
- protected SslHandler getSslHandler() {
- return sslHandler;
- }
-}
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Support.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Support.java
deleted file mode 100644
index 776744fd..00000000
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/Netty5Support.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.qpid.protonj2.test.driver.netty.netty5;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.buffer.BufferAllocator;
-
-/**
- * Support class used to detect if Netty 5 is available on the class path.
- */
-public final class Netty5Support {
-
- private static final Logger LOG = LoggerFactory.getLogger(Netty5Support.class);
-
- private static final Throwable UNAVAILABILITY_CAUSE;
- static {
- Throwable cause = null;
- try {
- BufferAllocator.onHeapUnpooled();
- } catch (Throwable ex) {
- LOG.debug("Netty 5 not available for use.");
- cause = ex;
- }
-
- UNAVAILABILITY_CAUSE = cause;
- }
-
- public static final boolean isAvailable() {
- return UNAVAILABILITY_CAUSE == null;
- }
-}
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/SslSupport.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/SslSupport.java
deleted file mode 100644
index 5fbdcae2..00000000
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/netty/netty5/SslSupport.java
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.test.driver.netty.netty5;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.lang.invoke.MethodHandles;
-import java.net.URI;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509ExtendedKeyManager;
-
-import org.apache.qpid.protonj2.test.driver.ProtonTestClientOptions;
-import org.apache.qpid.protonj2.test.driver.ProtonTestServerOptions;
-import org.apache.qpid.protonj2.test.driver.netty.X509AliasKeyManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.netty5.handler.ssl.SslHandler;
-import io.netty5.handler.ssl.util.InsecureTrustManagerFactory;
-
-/**
- * Static class that provides various utility methods used by Transport implementations.
- */
-public class SslSupport {
-
- private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- /**
- * Creates a Netty SslHandler instance for use in client instances that require
- * an SSL encoder / decoder.
- *
- * If the given options contain an SSLContext override, this will be used directly
- * when creating the handler. If they do not, an SSLContext will first be created
- * using the other option values.
- *
- * @param remote
- * The URI of the remote peer that the SslHandler will be used against.
- * @param options
- * The SSL options object to build the SslHandler instance from.
- *
- * @return a new SslHandler that is configured from the given options.
- *
- * @throws Exception if an error occurs while creating the SslHandler instance.
- */
- public static SslHandler createClientSslHandler(URI remote, ProtonTestClientOptions options) throws Exception {
- final SSLEngine sslEngine;
-
- SSLContext sslContext = options.getSslContextOverride();
- if (sslContext == null) {
- sslContext = createClientJdkSslContext(options);
- }
-
- sslEngine = createClientJdkSslEngine(remote, sslContext, options);
-
- return new SslHandler(sslEngine);
- }
-
- /**
- * Creates a Netty SslHandler instance for use in server instances that require
- * an SSL encoder / decoder.
- *
- * If the given options contain an SSLContext override, this will be used directly
- * when creating the handler. If they do not, an SSLContext will first be created
- * using the other option values.
- *
- * @param remote
- * The URI of the remote peer that the SslHandler will be used against.
- * @param options
- * The SSL options object to build the SslHandler instance from.
- *
- * @return a new SslHandler that is configured from the given options.
- *
- * @throws Exception if an error occurs while creating the SslHandler instance.
- */
- public static SslHandler createServerSslHandler(URI remote, ProtonTestServerOptions options) throws Exception {
- final SSLEngine sslEngine;
-
- SSLContext sslContext = options.getSslContextOverride();
- if (sslContext == null) {
- sslContext = createServerJdkSslContext(options);
- }
-
- sslEngine = createServerJdkSslEngine(remote, sslContext, options);
-
- return new SslHandler(sslEngine);
- }
-
- //----- JDK SSL Support Methods ------------------------------------------//
-
- /**
- * Create a new SSLContext using the options specific in the given TransportOptions
- * instance.
- *
- * @param options
- * the configured options used to create the SSLContext.
- *
- * @return a new SSLContext instance.
- *
- * @throws Exception if an error occurs while creating the context.
- */
- public static SSLContext createClientJdkSslContext(ProtonTestClientOptions options) throws Exception {
- try {
- String contextProtocol = options.getContextProtocol();
- LOG.trace("Getting SSLContext instance using protocol: {}", contextProtocol);
-
- SSLContext context = SSLContext.getInstance(contextProtocol);
-
- KeyManager[] keyMgrs = loadKeyManagers(options);
- TrustManager[] trustManagers = loadTrustManagers(options);
-
- context.init(keyMgrs, trustManagers, new SecureRandom());
- return context;
- } catch (Exception e) {
- LOG.error("Failed to create SSLContext: {}", e, e);
- throw e;
- }
- }
-
- /**
- * Create a new SSLContext using the options specific in the given TransportOptions
- * instance.
- *
- * @param options
- * the configured options used to create the SSLContext.
- *
- * @return a new SSLContext instance.
- *
- * @throws Exception if an error occurs while creating the context.
- */
- public static SSLContext createServerJdkSslContext(ProtonTestServerOptions options) throws Exception {
- try {
- String contextProtocol = options.getContextProtocol();
- LOG.trace("Getting SSLContext instance using protocol: {}", contextProtocol);
-
- SSLContext context = SSLContext.getInstance(contextProtocol);
-
- KeyManager[] keyMgrs = loadKeyManagers(options);
- TrustManager[] trustManagers = loadTrustManagers(options);
-
- context.init(keyMgrs, trustManagers, new SecureRandom());
- return context;
- } catch (Exception e) {
- LOG.error("Failed to create SSLContext: {}", e, e);
- throw e;
- }
- }
-
- /**
- * Create a new JDK SSLEngine instance in client mode from the given SSLContext and
- * TransportOptions instances.
- *
- * @param remote
- * the URI of the remote peer that will be used to initialize the engine, may be null if none should.
- * @param context
- * the SSLContext to use when creating the engine.
- * @param options
- * the TransportOptions to use to configure the new SSLEngine.
- *
- * @return a new SSLEngine instance in client mode.
- *
- * @throws Exception if an error occurs while creating the new SSLEngine.
- */
- public static SSLEngine createClientJdkSslEngine(URI remote, SSLContext context, ProtonTestClientOptions options) throws Exception {
- SSLEngine engine = null;
- if (remote == null) {
- engine = context.createSSLEngine();
- } else {
- engine = context.createSSLEngine(remote.getHost(), remote.getPort());
- }
-
- engine.setEnabledProtocols(buildEnabledProtocols(engine, options));
- engine.setEnabledCipherSuites(buildEnabledCipherSuites(engine, options));
- engine.setUseClientMode(true);
- engine.setNeedClientAuth(options.isNeedClientAuth());
-
- if (options.isVerifyHost()) {
- SSLParameters sslParameters = engine.getSSLParameters();
- sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
- engine.setSSLParameters(sslParameters);
- }
-
- return engine;
- }
-
- /**
- * Create a new JDK SSLEngine instance in client mode from the given SSLContext and
- * TransportOptions instances.
- *
- * @param remote
- * the URI of the remote peer that will be used to initialize the engine, may be null if none should.
- * @param context
- * the SSLContext to use when creating the engine.
- * @param options
- * the TransportOptions to use to configure the new SSLEngine.
- *
- * @return a new SSLEngine instance in client mode.
- *
- * @throws Exception if an error occurs while creating the new SSLEngine.
- */
- public static SSLEngine createServerJdkSslEngine(URI remote, SSLContext context, ProtonTestServerOptions options) throws Exception {
- SSLEngine engine = null;
- if (remote == null) {
- engine = context.createSSLEngine();
- } else {
- engine = context.createSSLEngine(remote.getHost(), remote.getPort());
- }
-
- engine.setEnabledProtocols(buildEnabledProtocols(engine, options));
- engine.setEnabledCipherSuites(buildEnabledCipherSuites(engine, options));
- engine.setUseClientMode(false);
- engine.setNeedClientAuth(options.isNeedClientAuth());
-
- if (options.isVerifyHost()) {
- SSLParameters sslParameters = engine.getSSLParameters();
- sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
- engine.setSSLParameters(sslParameters);
- }
-
- return engine;
- }
-
- //----- Internal support methods -----------------------------------------//
-
- private static String[] buildEnabledProtocols(SSLEngine engine, ProtonTestClientOptions options) {
- List<String> enabledProtocols = new ArrayList<>();
-
- if (options.getEnabledProtocols() != null) {
- List<String> configuredProtocols = Arrays.asList(options.getEnabledProtocols());
- LOG.trace("Configured protocols from transport options: {}", configuredProtocols);
- enabledProtocols.addAll(configuredProtocols);
- } else {
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- LOG.trace("Default protocols from the SSLEngine: {}", engineProtocols);
- enabledProtocols.addAll(engineProtocols);
- }
-
- String[] disabledProtocols = options.getDisabledProtocols();
- if (disabledProtocols != null) {
- List<String> disabled = Arrays.asList(disabledProtocols);
- LOG.trace("Disabled protocols: {}", disabled);
- enabledProtocols.removeAll(disabled);
- }
-
- LOG.trace("Enabled protocols: {}", enabledProtocols);
-
- return enabledProtocols.toArray(new String[0]);
- }
-
- private static String[] buildEnabledProtocols(SSLEngine engine, ProtonTestServerOptions options) {
- List<String> enabledProtocols = new ArrayList<>();
-
- if (options.getEnabledProtocols() != null) {
- List<String> configuredProtocols = Arrays.asList(options.getEnabledProtocols());
- LOG.trace("Configured protocols from transport options: {}", configuredProtocols);
- enabledProtocols.addAll(configuredProtocols);
- } else {
- List<String> engineProtocols = Arrays.asList(engine.getEnabledProtocols());
- LOG.trace("Default protocols from the SSLEngine: {}", engineProtocols);
- enabledProtocols.addAll(engineProtocols);
- }
-
- String[] disabledProtocols = options.getDisabledProtocols();
- if (disabledProtocols != null) {
- List<String> disabled = Arrays.asList(disabledProtocols);
- LOG.trace("Disabled protocols: {}", disabled);
- enabledProtocols.removeAll(disabled);
- }
-
- LOG.trace("Enabled protocols: {}", enabledProtocols);
-
- return enabledProtocols.toArray(new String[0]);
- }
-
- private static String[] buildEnabledCipherSuites(SSLEngine engine, ProtonTestServerOptions options) {
- List<String> enabledCipherSuites = new ArrayList<>();
-
- if (options.getEnabledCipherSuites() != null) {
- List<String> configuredCipherSuites = Arrays.asList(options.getEnabledCipherSuites());
- LOG.trace("Configured cipher suites from transport options: {}", configuredCipherSuites);
- enabledCipherSuites.addAll(configuredCipherSuites);
- } else {
- List<String> engineCipherSuites = Arrays.asList(engine.getEnabledCipherSuites());
- LOG.trace("Default cipher suites from the SSLEngine: {}", engineCipherSuites);
- enabledCipherSuites.addAll(engineCipherSuites);
- }
-
- String[] disabledCipherSuites = options.getDisabledCipherSuites();
- if (disabledCipherSuites != null) {
- List<String> disabled = Arrays.asList(disabledCipherSuites);
- LOG.trace("Disabled cipher suites: {}", disabled);
- enabledCipherSuites.removeAll(disabled);
- }
-
- LOG.trace("Enabled cipher suites: {}", enabledCipherSuites);
-
- return enabledCipherSuites.toArray(new String[0]);
- }
-
- private static String[] buildEnabledCipherSuites(SSLEngine engine, ProtonTestClientOptions options) {
- List<String> enabledCipherSuites = new ArrayList<>();
-
- if (options.getEnabledCipherSuites() != null) {
- List<String> configuredCipherSuites = Arrays.asList(options.getEnabledCipherSuites());
- LOG.trace("Configured cipher suites from transport options: {}", configuredCipherSuites);
- enabledCipherSuites.addAll(configuredCipherSuites);
- } else {
- List<String> engineCipherSuites = Arrays.asList(engine.getEnabledCipherSuites());
- LOG.trace("Default cipher suites from the SSLEngine: {}", engineCipherSuites);
- enabledCipherSuites.addAll(engineCipherSuites);
- }
-
- String[] disabledCipherSuites = options.getDisabledCipherSuites();
- if (disabledCipherSuites != null) {
- List<String> disabled = Arrays.asList(disabledCipherSuites);
- LOG.trace("Disabled cipher suites: {}", disabled);
- enabledCipherSuites.removeAll(disabled);
- }
-
- LOG.trace("Enabled cipher suites: {}", enabledCipherSuites);
-
- return enabledCipherSuites.toArray(new String[0]);
- }
-
- private static TrustManager[] loadTrustManagers(ProtonTestClientOptions options) throws Exception {
- TrustManagerFactory factory = loadTrustManagerFactory(options);
- if (factory != null) {
- return factory.getTrustManagers();
- } else {
- return null;
- }
- }
-
- private static TrustManager[] loadTrustManagers(ProtonTestServerOptions options) throws Exception {
- TrustManagerFactory factory = loadTrustManagerFactory(options);
- if (factory != null) {
- return factory.getTrustManagers();
- } else {
- return null;
- }
- }
-
- private static TrustManagerFactory loadTrustManagerFactory(ProtonTestClientOptions options) throws Exception {
- if (options.isTrustAll()) {
- return InsecureTrustManagerFactory.INSTANCE;
- }
-
- if (options.getTrustStoreLocation() == null) {
- return null;
- }
-
- TrustManagerFactory fact = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-
- String storeLocation = options.getTrustStoreLocation();
- String storePassword = options.getTrustStorePassword();
- String storeType = options.getTrustStoreType();
-
- LOG.trace("Attempt to load TrustStore from location {} of type {}", storeLocation, storeType);
-
- KeyStore trustStore = loadStore(storeLocation, storePassword, storeType);
- fact.init(trustStore);
-
- return fact;
- }
-
- private static TrustManagerFactory loadTrustManagerFactory(ProtonTestServerOptions options) throws Exception {
- if (options.isTrustAll()) {
- return InsecureTrustManagerFactory.INSTANCE;
- }
-
- if (options.getTrustStoreLocation() == null) {
- return null;
- }
-
- TrustManagerFactory fact = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-
- String storeLocation = options.getTrustStoreLocation();
- String storePassword = options.getTrustStorePassword();
- String storeType = options.getTrustStoreType();
-
- LOG.trace("Attempt to load TrustStore from location {} of type {}", storeLocation, storeType);
-
- KeyStore trustStore = loadStore(storeLocation, storePassword, storeType);
- fact.init(trustStore);
-
- return fact;
- }
-
- private static KeyManager[] loadKeyManagers(ProtonTestClientOptions options) throws Exception {
- if (options.getKeyStoreLocation() == null) {
- return null;
- }
-
- KeyManagerFactory fact = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-
- String storeLocation = options.getKeyStoreLocation();
- String storePassword = options.getKeyStorePassword();
- String storeType = options.getKeyStoreType();
- String alias = options.getKeyAlias();
-
- LOG.trace("Attempt to load KeyStore from location {} of type {}", storeLocation, storeType);
-
- KeyStore keyStore = loadStore(storeLocation, storePassword, storeType);
- fact.init(keyStore, storePassword != null ? storePassword.toCharArray() : null);
-
- if (alias == null) {
- return fact.getKeyManagers();
- } else {
- validateAlias(keyStore, alias);
- return wrapKeyManagers(alias, fact.getKeyManagers());
- }
- }
-
- private static KeyManager[] loadKeyManagers(ProtonTestServerOptions options) throws Exception {
- if (options.getKeyStoreLocation() == null) {
- return null;
- }
-
- KeyManagerFactory fact = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-
- String storeLocation = options.getKeyStoreLocation();
- String storePassword = options.getKeyStorePassword();
- String storeType = options.getKeyStoreType();
- String alias = options.getKeyAlias();
-
- LOG.trace("Attempt to load KeyStore from location {} of type {}", storeLocation, storeType);
-
- KeyStore keyStore = loadStore(storeLocation, storePassword, storeType);
- fact.init(keyStore, storePassword != null ? storePassword.toCharArray() : null);
-
- if (alias == null) {
- return fact.getKeyManagers();
- } else {
- validateAlias(keyStore, alias);
- return wrapKeyManagers(alias, fact.getKeyManagers());
- }
- }
-
- private static KeyManager[] wrapKeyManagers(String alias, KeyManager[] origKeyManagers) {
- KeyManager[] keyManagers = new KeyManager[origKeyManagers.length];
- for (int i = 0; i < origKeyManagers.length; i++) {
- KeyManager km = origKeyManagers[i];
- if (km instanceof X509ExtendedKeyManager) {
- km = new X509AliasKeyManager(alias, (X509ExtendedKeyManager) km);
- }
-
- keyManagers[i] = km;
- }
-
- return keyManagers;
- }
-
- private static void validateAlias(KeyStore store, String alias) throws IllegalArgumentException, KeyStoreException {
- if (!store.containsAlias(alias)) {
- throw new IllegalArgumentException("The alias '" + alias + "' doesn't exist in the key store");
- }
-
- if (!store.isKeyEntry(alias)) {
- throw new IllegalArgumentException("The alias '" + alias + "' in the keystore doesn't represent a key entry");
- }
- }
-
- private static KeyStore loadStore(String storePath, final String password, String storeType) throws Exception {
- KeyStore store = KeyStore.getInstance(storeType);
- try (InputStream in = new FileInputStream(new File(storePath));) {
- store.load(in, password != null ? password.toCharArray() : null);
- }
-
- return store;
- }
-}
diff --git a/protonj2/pom.xml b/protonj2/pom.xml
index 59d7c0c6..c919c19d 100644
--- a/protonj2/pom.xml
+++ b/protonj2/pom.xml
@@ -39,11 +39,6 @@
<artifactId>netty-buffer</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty5-buffer</artifactId>
- <scope>provided</scope>
- </dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>proton-j</artifactId>
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/Netty5ProtonBufferAllocator.java b/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/Netty5ProtonBufferAllocator.java
deleted file mode 100644
index bb3d972b..00000000
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/Netty5ProtonBufferAllocator.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.qpid.protonj2.buffer.netty;
-
-import java.nio.ByteBuffer;
-
-import org.apache.qpid.protonj2.buffer.ProtonBuffer;
-import org.apache.qpid.protonj2.buffer.ProtonBufferAllocator;
-import org.apache.qpid.protonj2.buffer.ProtonCompositeBuffer;
-
-import io.netty5.buffer.Buffer;
-import io.netty5.buffer.BufferAllocator;
-
-/**
- * Proton managed Netty 5 {@link BufferAllocator} wrapper.
- */
-public final class Netty5ProtonBufferAllocator implements ProtonBufferAllocator {
-
- public static int DEFAULT_CAPACITY = 1024;
-
- public static ProtonBufferAllocator POOLED = new Netty5ProtonBufferAllocator(BufferAllocator.onHeapPooled());
-
- public static ProtonBufferAllocator UNPOOLED = new Netty5ProtonBufferAllocator(BufferAllocator.onHeapUnpooled());
-
- private boolean closed;
-
- private final BufferAllocator allocator;
-
- public Netty5ProtonBufferAllocator(BufferAllocator allocator) {
- this.allocator = allocator;
- }
-
- public BufferAllocator allocator() {
- return allocator;
- }
-
- @Override
- public void close() {
- closed = true;
- }
-
- /**
- * Creates a {@link ProtonBuffer} wrapper around the given Netty 5 based
- * Buffer instance. The method wraps a Buffer and assumes ownership of it
- * which means that once the wrapper buffer is closed it will release the
- * {@link Buffer} which if there are no other references will render the
- * wrapped buffer closed and recyclable if pooled. Care should be take
- * when supplying the buffer to add a reference depending on the source of
- * the buffer.
- *
- * @param buffer
- * The buffer instance to wrap.
- *
- * @return A ProtonBuffer instance that wraps the given netty buffer.
- */
- public Netty5ToProtonBufferAdapter wrap(Buffer buffer) {
- checkClosed();
- return new Netty5ToProtonBufferAdapter(this, buffer);
- }
-
- @Override
- public Netty5ToProtonBufferAdapter outputBuffer(int initialCapacity) {
- return allocate(initialCapacity);
- }
-
- @Override
- public Netty5ToProtonBufferAdapter allocate() {
- return allocate(DEFAULT_CAPACITY);
- }
-
- @Override
- public Netty5ToProtonBufferAdapter allocate(int initialCapacity) {
- checkClosed();
- return new Netty5ToProtonBufferAdapter(this, allocator.allocate(initialCapacity));
- }
-
- @Override
- public Netty5ToProtonBufferAdapter allocateHeapBuffer() {
- return allocateHeapBuffer(DEFAULT_CAPACITY);
- }
-
- @Override
- public Netty5ToProtonBufferAdapter allocateHeapBuffer(int initialCapacity) {
- checkClosed();
- return new Netty5ToProtonBufferAdapter(this, BufferAllocator.onHeapUnpooled().allocate(initialCapacity));
- }
-
- @Override
- public Netty5ToProtonBufferAdapter copy(byte[] array) {
- checkClosed();
- return new Netty5ToProtonBufferAdapter(this, allocator.copyOf(array));
- }
-
- @Override
- public Netty5ToProtonBufferAdapter copy(byte[] array, int offset, int length) {
- checkClosed();
- return new Netty5ToProtonBufferAdapter(this, allocator.copyOf(ByteBuffer.wrap(array, offset, length)));
- }
-
- @Override
- public ProtonCompositeBuffer composite() {
- checkClosed();
- return ProtonCompositeBuffer.create(this);
- }
-
- @Override
- public ProtonCompositeBuffer composite(ProtonBuffer buffer) {
- checkClosed();
- return ProtonCompositeBuffer.create(this, buffer);
- }
-
- @Override
- public ProtonCompositeBuffer composite(ProtonBuffer[] buffers) {
- checkClosed();
- return ProtonCompositeBuffer.create(this, buffers);
- }
-
- private void checkClosed() {
- if (closed) {
- throw new IllegalStateException("This allocator instance is closed");
- }
- }
-}
-
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/Netty5ToProtonBufferAdapter.java b/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/Netty5ToProtonBufferAdapter.java
deleted file mode 100644
index 96dd8c99..00000000
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/Netty5ToProtonBufferAdapter.java
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.qpid.protonj2.buffer.netty;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.nio.charset.Charset;
-import java.util.NoSuchElementException;
-
-import org.apache.qpid.protonj2.buffer.ProtonBuffer;
-import org.apache.qpid.protonj2.buffer.ProtonBufferClosedException;
-import org.apache.qpid.protonj2.buffer.ProtonBufferComponent;
-import org.apache.qpid.protonj2.buffer.ProtonBufferComponentAccessor;
-import org.apache.qpid.protonj2.buffer.ProtonBufferIterator;
-import org.apache.qpid.protonj2.buffer.ProtonBufferUtils;
-import org.apache.qpid.protonj2.resource.SharedResource;
-
-import io.netty5.buffer.Buffer;
-import io.netty5.buffer.BufferAllocator;
-import io.netty5.buffer.BufferClosedException;
-import io.netty5.buffer.BufferComponent;
-import io.netty5.buffer.BufferReadOnlyException;
-import io.netty5.buffer.ByteCursor;
-import io.netty5.buffer.ComponentIterator;
-import io.netty5.buffer.ComponentIterator.Next;
-
-/**
- * Wrapper class for Netty 5 Buffer instances which provides a generic way
- * for proton to interact with Netty 4 buffers.
- */
-public final class Netty5ToProtonBufferAdapter extends SharedResource<ProtonBuffer>
- implements ProtonBuffer, ProtonBufferComponentAccessor, ProtonBufferComponent {
-
- private final Netty5ProtonBufferAllocator allocator;
-
- private static final Buffer CLOSED_BUFFER;
-
- static {
- CLOSED_BUFFER = BufferAllocator.onHeapUnpooled().allocate(0);
- CLOSED_BUFFER.close();
- }
-
- private Buffer resource;
- private BufferComponent resourceComponent;
-
- /**
- * Creates a new {@link Netty5ToProtonBufferAdapter} which wraps the given Netty {@link Buffer}.
- *
- * @param allocator
- * The allocator that created this buffer wrapper
- * @param resource
- * The {@link Buffer} resource to wrap.
- */
- public Netty5ToProtonBufferAdapter(Netty5ProtonBufferAllocator allocator, Buffer resource) {
- this.resource = resource;
- this.allocator = allocator;
-
- // To avoid allocation of component iterators we can check that the buffer
- // is a single component buffer and it implements the component interface as
- // Netty optimizes this case to also avoid allocations.
- if (resource.countComponents() == 1 && resource instanceof BufferComponent) {
- resourceComponent = (BufferComponent) resource;
- }
- }
-
- public Netty5ProtonBufferAllocator allocator() {
- return allocator;
- }
-
- /**
- * Unwraps the managed Netty {@link Buffer} and releases it from ownership by this
- * {@link ProtonBuffer} instance. This effectively closes the {@link ProtonBuffer}
- * while also safely handing off the managed Netty resource.
- *
- * @return the managed Netty {@link Buffer}
- */
- public Buffer unwrapAndRelease() {
- if (resource != CLOSED_BUFFER) {
- try {
- return resource;
- } finally {
- resource = CLOSED_BUFFER;
- }
- } else {
- throw new ProtonBufferClosedException("The buffer has already been closed or transferred");
- }
- }
-
- @Override
- public Buffer unwrap() {
- ProtonBufferUtils.checkIsClosed(this);
- return resource;
- }
-
- @Override
- public ProtonBuffer convertToReadOnly() {
- resource.makeReadOnly();
- return this;
- }
-
- @Override
- public boolean isReadOnly() {
- return resource.readOnly();
- }
-
- @Override
- public boolean isComposite() {
- return false;
- }
-
- @Override
- public int componentCount() {
- return resource.countComponents();
- }
-
- @Override
- public int readableComponentCount() {
- return resource.countReadableComponents();
- }
-
- @Override
- public int writableComponentCount() {
- return resource.countWritableComponents();
- }
-
- @Override
- public boolean isDirect() {
- return false; // Buffer components APIs need to allow access to native addresses
- }
-
- @Override
- public int implicitGrowthLimit() {
- return resource.implicitCapacityLimit();
- }
-
- @Override
- public ProtonBuffer implicitGrowthLimit(int limit) {
- resource.implicitCapacityLimit(limit);
- return this;
- }
-
- @Override
- public ProtonBuffer fill(byte value) {
- try {
- resource.fill(value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public int capacity() {
- return resource.capacity();
- }
-
- @Override
- public int getReadOffset() {
- return resource.readerOffset();
- }
-
- @Override
- public ProtonBuffer setReadOffset(int value) {
- resource.readerOffset(value);
- return this;
- }
-
- @Override
- public int getWriteOffset() {
- return resource.writerOffset();
- }
-
- @Override
- public ProtonBuffer setWriteOffset(int value) {
- try {
- resource.writerOffset(value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer compact() {
- try {
- resource.compact();
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public void copyInto(int offset, byte[] destination, int destOffset, int length) {
- try {
- resource.copyInto(offset, destination, destOffset, length);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public void copyInto(int offset, ByteBuffer destination, int destOffset, int length) {
- try {
- resource.copyInto(offset, destination, destOffset, length);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public void copyInto(int offset, ProtonBuffer destination, int destOffset, int length) {
- try {
- if (destination.unwrap() instanceof Buffer) {
- resource.copyInto(offset, (Buffer) destination.unwrap(), destOffset, length);
- } else {
- ProtonBufferUtils.checkIsReadOnly(destination);
- ProtonBufferUtils.checkIsClosed(this);
-
- // Try to reduce bounds-checking by using larger primitives when possible.
- for (; length >= Long.BYTES; length -= Long.BYTES, offset += Long.BYTES, destOffset += Long.BYTES) {
- destination.setLong(destOffset, getLong(offset));
- }
- for (; length >= Integer.BYTES; length -= Integer.BYTES, offset += Integer.BYTES, destOffset += Integer.BYTES) {
- destination.setInt(destOffset, getInt(offset));
- }
- for (; length > 0; length--, offset++, destOffset++) {
- destination.setByte(destOffset, getByte(offset));
- }
- }
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public ProtonBuffer writeBytes(byte[] source, int offset, int length) {
- try {
- resource.writeBytes(source, offset, length);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
-
- return this;
- }
-
- @Override
- public ProtonBuffer writeBytes(ByteBuffer source) {
- try {
- resource.writeBytes(source);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
-
- return this;
- }
-
- @Override
- public ProtonBuffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction) throws IndexOutOfBoundsException, IllegalArgumentException {
- try {
- resource.ensureWritable(size, minimumGrowth, allowCompaction);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
-
- return this;
- }
-
- @Override
- public ProtonBuffer copy(int index, int length, boolean readOnly) throws IllegalArgumentException {
- try {
- return allocator.wrap(resource.copy(index, length, readOnly));
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public ProtonBuffer split(int splitOffset) {
- try {
- return allocator.wrap(resource.split(splitOffset));
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- //----- JDK Overrides
-
- @Override
- public String toString(Charset charset) {
- return resource.toString(charset);
- }
-
- @Override
- public String toString() {
- return "Netty5ToProtonBufferAdapter" +
- "{ read:" + (resource != null ? resource.readerOffset() : null) +
- ", write: " + (resource != null ? resource.writerOffset() : 0) +
- ", capacity: " + (resource != null ? resource.capacity() : 0) + "}";
- }
-
- @Override
- public int compareTo(ProtonBuffer buffer) {
- return ProtonBufferUtils.compare(this, buffer);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ProtonBuffer) {
- return ProtonBufferUtils.equals(this, (ProtonBuffer) other);
- }
-
- return false;
- }
-
- @Override
- public int hashCode() {
- return ProtonBufferUtils.hashCode(this);
- }
-
- //----- Primitive Get API
-
- @Override
- public byte getByte(int index) {
- try {
- return resource.getByte(index);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public char getChar(int index) {
- try {
- return resource.getChar(index);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public short getShort(int index) {
- try {
- return resource.getShort(index);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public int getInt(int index) {
- try {
- return resource.getInt(index);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public long getLong(int index) {
- try {
- return resource.getLong(index);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- //----- Primitive Set API
-
- @Override
- public ProtonBuffer setByte(int index, byte value) {
- try {
- resource.setByte(index, value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer setChar(int index, char value) {
- try {
- resource.setChar(index, value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer setShort(int index, short value) {
- try {
- resource.setShort(index, value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer setInt(int index, int value) {
- try {
- resource.setInt(index, value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer setLong(int index, long value) {
- try {
- resource.setLong(index, value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- //----- Primitive Read API
-
- @Override
- public byte readByte() {
- try {
- return resource.readByte();
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public char readChar() {
- try {
- return resource.readChar();
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public short readShort() {
- try {
- return resource.readShort();
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public int readInt() {
- try {
- return resource.readInt();
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public long readLong() {
- try {
- return resource.readLong();
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- //----- Primitive Write API
-
- @Override
- public ProtonBuffer writeByte(byte value) {
- try {
- resource.writeByte(value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer writeChar(char value) {
- try {
- resource.writeChar(value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer writeShort(short value) {
- try {
- resource.writeShort(value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer writeInt(int value) {
- try {
- resource.writeInt(value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- @Override
- public ProtonBuffer writeLong(long value) {
- try {
- resource.writeLong(value);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- return this;
- }
-
- //----- IO Handlers
-
- @Override
- public int transferTo(WritableByteChannel channel, int length) throws IOException {
- try {
- return resource.transferTo(channel, length);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public int transferFrom(ReadableByteChannel channel, int length) throws IOException {
- try {
- return resource.transferFrom(channel, length);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- @Override
- public int transferFrom(FileChannel channel, long position, int length) throws IOException {
- try {
- return resource.transferFrom(channel, position, length);
- } catch (RuntimeException e) {
- throw translateToProtonException(e);
- }
- }
-
- //----- Buff component access
-
- @Override
- public ProtonBufferComponentAccessor componentAccessor() {
- if (isClosed()) {
- throw ProtonBufferUtils.genericBufferIsClosed(this);
- }
-
- if (resourceComponent != null) {
- return (ProtonBufferComponentAccessor) acquire();
- } else {
- return new ProtonNetty5BufferComponentAccessor((Netty5ToProtonBufferAdapter) acquire(), resource.forEachComponent());
- }
- }
-
- @Override
- public ProtonBufferComponent first() {
- return this;
- }
-
- @Override
- public ProtonBufferComponent next() {
- return null;
- }
-
- //----- Buffer Component API that works only when there is one component in the netty buffer
-
- @Override
- public int getReadableBytes() {
- return resourceComponent.readableBytes();
- }
-
- @Override
- public boolean hasReadbleArray() {
- return resourceComponent.hasReadableArray();
- }
-
- @Override
- public Netty5ToProtonBufferAdapter advanceReadOffset(int amount) {
- return (Netty5ToProtonBufferAdapter) ProtonBuffer.super.advanceReadOffset(amount);
- }
-
- @Override
- public byte[] getReadableArray() {
- return resourceComponent.readableArray();
- }
-
- @Override
- public int getReadableArrayOffset() {
- return resourceComponent.readableArrayOffset();
- }
-
- @Override
- public int getReadableArrayLength() {
- return resourceComponent.readableArrayLength();
- }
-
- @Override
- public ByteBuffer getReadableBuffer() {
- return resourceComponent.readableBuffer();
- }
-
- @Override
- public int getWritableBytes() {
- return resourceComponent.writableBytes();
- }
-
- @Override
- public Netty5ToProtonBufferAdapter advanceWriteOffset(int amount) {
- return (Netty5ToProtonBufferAdapter) ProtonBuffer.super.advanceWriteOffset(amount);
- }
-
- @Override
- public boolean hasWritableArray() {
- return resourceComponent.hasWritableArray();
- }
-
- @Override
- public byte[] getWritableArray() {
- return resourceComponent.writableArray();
- }
-
- @Override
- public int getWritableArrayOffset() {
- return resourceComponent.writableArrayOffset();
- }
-
- @Override
- public int getWritableArrayLength() {
- return resourceComponent.writableArrayLength();
- }
-
- @Override
- public ByteBuffer getWritableBuffer() {
- return resourceComponent.writableBuffer();
- }
-
- @Override
- public long getNativeAddress() {
- return resourceComponent.baseNativeAddress();
- }
-
- @Override
- public long getNativeReadAddress() {
- return resourceComponent.readableNativeAddress();
- }
-
- @Override
- public long getNativeWriteAddress() {
- return resourceComponent.writableNativeAddress();
- }
-
- //----- Buffer Iteration API
-
- @Override
- public ProtonBufferIterator bufferIterator() {
- return bufferIterator(getReadOffset(), getReadableBytes());
- }
-
- @Override
- public ProtonBufferIterator bufferIterator(int offset, int length) {
- ProtonBufferUtils.checkIsClosed(this);
- ProtonBufferUtils.checkIsNotNegative(length, "length");
- ProtonBufferUtils.checkIsNotNegative(offset, "length");
-
- if (offset + length > resource.capacity()) {
- throw new IndexOutOfBoundsException(
- "The iterator cannot read beyond the bounds of the buffer: offset=" + offset + ", length=" + length);
- }
-
- return new Netty5ToProtonBufferReverseIterator(resource.openCursor(offset, length));
- }
-
- @Override
- public ProtonBufferIterator bufferReverseIterator(int offset, int length) {
- ProtonBufferUtils.checkIsClosed(this);
- ProtonBufferUtils.checkIsNotNegative(length, "length");
- ProtonBufferUtils.checkIsNotNegative(offset, "length");
-
- if (offset >= capacity()) {
- throw new IndexOutOfBoundsException(
- "Read offset must be within the bounds of the buffer: offset = " + offset + ", capacity = " + capacity());
- }
-
- if (offset - length < -1) {
- throw new IndexOutOfBoundsException(
- "Cannot read past start of buffer: offset = " + offset + ", length = " + length);
- }
-
- return new Netty5ToProtonBufferReverseIterator(resource.openReverseCursor(offset, length));
- }
-
- private static final class Netty5ToProtonBufferReverseIterator implements ProtonBufferIterator {
-
- private final ByteCursor cursor;
-
- public Netty5ToProtonBufferReverseIterator(ByteCursor cursor) {
- this.cursor = cursor;
- }
-
- @Override
- public boolean hasNext() {
- return cursor.bytesLeft() > 0;
- }
-
- @Override
- public byte next() {
- if (!cursor.readByte()) {
- throw new NoSuchElementException("Cannot read outside the iterator bounds");
- }
-
- return cursor.getByte();
- }
-
- @Override
- public int remaining() {
- return cursor.bytesLeft();
- }
-
- @Override
- public int offset() {
- return cursor.currentOffset();
- }
- }
-
- //----- Buffer search API
-
- @Override
- public int indexOf(byte needle, int offset, int length) {
- ProtonBufferUtils.checkIsClosed(this);
-
- if (offset < getReadOffset() || getWriteOffset() < offset + length) {
- throw new IndexOutOfBoundsException("Cannot search past the readable bounds of this buffer");
- }
-
- final int count = resource.bytesBefore(needle);
- if (count < 0) {
- return count;
- }
-
- final int indexOf = offset + count;
-
- if (offset > indexOf || offset + length < indexOf) {
- return -1;
- }
-
- return indexOf;
- }
-
- //----- Shared resource API
-
- @Override
- protected void releaseResourceOwnership() {
- if (resource != null && resource.isAccessible()) {
- resource.close();
- resource = CLOSED_BUFFER;
- }
- }
-
- @Override
- protected ProtonBuffer transferTheResource() {
- final Buffer transferred = resource;
- resource = CLOSED_BUFFER;
-
- return new Netty5ToProtonBufferAdapter(allocator, transferred);
- }
-
- @Override
- protected RuntimeException resourceIsClosedException() {
- return ProtonBufferUtils.genericBufferIsClosed(this);
- }
-
- //----- Support API for the buffer wrapper
-
- private RuntimeException translateToProtonException(RuntimeException e) {
- RuntimeException result = e;
-
- if (e instanceof BufferReadOnlyException) {
- result = ProtonBufferUtils.genericBufferIsReadOnly(this);
- result.addSuppressed(e);
- } else if (e instanceof BufferClosedException) {
- result = ProtonBufferUtils.genericBufferIsClosed(this);
- result.addSuppressed(e);
- }
-
- return result;
- }
-
- @SuppressWarnings("rawtypes")
- private static final class ProtonNetty5BufferComponentAccessor implements ProtonBufferComponentAccessor, ProtonBufferComponent {
-
- private final Netty5ToProtonBufferAdapter adapter;
-
- private final ComponentIterator resourceIterator;
-
- private Next current;
- private BufferComponent currentComponent;
-
- public ProtonNetty5BufferComponentAccessor(Netty5ToProtonBufferAdapter adapter, ComponentIterator iterator) {
- this.adapter = adapter;
- this.resourceIterator = iterator;
- }
-
- @Override
- public void close() {
- current = null;
- currentComponent = null;
-
- resourceIterator.close();
- adapter.close();
- }
-
- @Override
- public ProtonBufferComponent first() {
- current = resourceIterator.first();
- currentComponent = (BufferComponent) current;
-
- return this;
- }
-
- @Override
- public ProtonBufferComponent next() {
- if (current != null) {
- current = current.next();
- currentComponent = (BufferComponent) current;
- }
-
- return current != null ? this : null;
- }
-
- @Override
- public Object unwrap() {
- return adapter.resource;
- }
-
- @Override
- public int getReadableBytes() {
- return currentComponent.readableBytes();
- }
-
- @Override
- public boolean hasReadbleArray() {
- return currentComponent.hasReadableArray();
- }
-
- @Override
- public ProtonBufferComponent advanceReadOffset(int amount) {
- currentComponent.skipReadableBytes(amount);
- return this;
- }
-
- @Override
- public byte[] getReadableArray() {
- return currentComponent.readableArray();
- }
-
- @Override
- public int getReadableArrayOffset() {
- return currentComponent.readableArrayOffset();
- }
-
- @Override
- public int getReadableArrayLength() {
- return currentComponent.readableArrayLength();
- }
-
- @Override
- public ByteBuffer getReadableBuffer() {
- return currentComponent.readableBuffer();
- }
-
- @Override
- public int getWritableBytes() {
- return currentComponent.writableBytes();
- }
-
- @Override
- public ProtonBufferComponent advanceWriteOffset(int amount) {
- currentComponent.skipWritableBytes(amount);
- return this;
- }
-
- @Override
- public boolean hasWritableArray() {
- return currentComponent.hasWritableArray();
- }
-
- @Override
- public byte[] getWritableArray() {
- return currentComponent.writableArray();
- }
-
- @Override
- public int getWritableArrayOffset() {
- return currentComponent.writableArrayOffset();
- }
-
- @Override
- public int getWritableArrayLength() {
- return currentComponent.writableArrayLength();
- }
-
- @Override
- public ByteBuffer getWritableBuffer() {
- return currentComponent.writableBuffer();
- }
-
- @Override
- public long getNativeAddress() {
- return currentComponent.baseNativeAddress();
- }
-
- @Override
- public long getNativeReadAddress() {
- return currentComponent.readableNativeAddress();
- }
-
- @Override
- public long getNativeWriteAddress() {
- return currentComponent.writableNativeAddress();
- }
-
- @Override
- public ProtonBufferIterator bufferIterator() {
- return new Netty5ToProtonBufferIterator(currentComponent.openCursor());
- }
-
- private final class Netty5ToProtonBufferIterator implements ProtonBufferIterator {
-
- private final ByteCursor cursor;
-
- public Netty5ToProtonBufferIterator(ByteCursor cursor) {
- this.cursor = cursor;
- }
-
- @Override
- public boolean hasNext() {
- return cursor.bytesLeft() > 0;
- }
-
- @Override
- public byte next() {
- if (cursor.readByte()) {
- throw new NoSuchElementException("Cannot read outside the iterator bounds");
- }
-
- return cursor.getByte();
- }
-
- @Override
- public int remaining() {
- return cursor.bytesLeft();
- }
-
- @Override
- public int offset() {
- return cursor.currentOffset();
- }
- }
- }
-}
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/ProtonBufferToNetty5Adapter.java b/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/ProtonBufferToNetty5Adapter.java
deleted file mode 100644
index 2125e7a3..00000000
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/buffer/netty/ProtonBufferToNetty5Adapter.java
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.qpid.protonj2.buffer.netty;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.nio.charset.Charset;
-
-import org.apache.qpid.protonj2.buffer.ProtonBuffer;
-import org.apache.qpid.protonj2.buffer.ProtonBufferClosedException;
-import org.apache.qpid.protonj2.buffer.ProtonBufferComponent;
-import org.apache.qpid.protonj2.buffer.ProtonBufferComponentAccessor;
-import org.apache.qpid.protonj2.buffer.ProtonBufferIterator;
-import org.apache.qpid.protonj2.buffer.ProtonBufferReadOnlyException;
-
-import io.netty5.buffer.Buffer;
-import io.netty5.buffer.BufferClosedException;
-import io.netty5.buffer.BufferComponent;
-import io.netty5.buffer.BufferReadOnlyException;
-import io.netty5.buffer.ByteCursor;
-import io.netty5.buffer.ComponentIterator;
-import io.netty5.buffer.ComponentIterator.Next;
-import io.netty5.buffer.internal.InternalBufferUtils;
-import io.netty5.util.Send;
-
-/**
- * Adapts a {@link ProtonBuffer} instance to a Netty 5 {@link Buffer}
- */
-public class ProtonBufferToNetty5Adapter implements Buffer {
-
- private ProtonBuffer resource;
-
- public ProtonBufferToNetty5Adapter(ProtonBuffer resource) {
- this.resource = resource;
- }
-
- @Override
- public void close() {
- resource.close();
- }
-
- @Override
- public Send<Buffer> send() {
- try {
- final ProtonBuffer transferred = resource.transfer();
-
- return new Send<Buffer>() {
-
- @Override
- public Buffer receive() {
- return new ProtonBufferToNetty5Adapter(transferred);
- }
-
- @Override
- public void close() {
- transferred.close();
- }
-
- @Override
- public boolean referentIsInstanceOf(Class<?> cls) {
- return cls.isAssignableFrom(ProtonBufferToNetty5Adapter.class);
- }
- };
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public boolean isAccessible() {
- return !resource.isClosed();
- }
-
- @Override
- public Buffer compact() {
- try {
- resource.compact();
- return this;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public Buffer makeReadOnly() {
- try {
- resource.convertToReadOnly();
- return this;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public boolean readOnly() {
- return resource.isReadOnly();
- }
-
- @Override
- public Buffer fill(byte value) {
- try {
- resource.fill(value);
- return this;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public boolean isDirect() {
- return false; // NOTE: resource.isDirect(); is only reasonable if we also expose the native address
- }
-
- @Override
- public int capacity() {
- return resource.capacity();
- }
-
- @Override
- public Buffer implicitCapacityLimit(int limit) {
- try {
- resource.implicitGrowthLimit(limit);
- return this;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public int implicitCapacityLimit() {
- return resource.implicitGrowthLimit();
- }
-
- @Override
- public int readerOffset() {
- return resource.getReadOffset();
- }
-
- @Override
- public Buffer readerOffset(int offset) {
- try {
- resource.setReadOffset(offset);
- return this;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public int writerOffset() {
- return resource.getWriteOffset();
- }
-
- @Override
- public Buffer writerOffset(int offset) {
- try {
- resource.setWriteOffset(offset);
- return this;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public Buffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction) {
- try {
- resource.ensureWritable(size, minimumGrowth, allowCompaction);
- return this;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public void copyInto(int srcPos, byte[] dest, int destPos, int length) {
- try {
- resource.copyInto(srcPos, dest, destPos, length);
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public void copyInto(int srcPos, ByteBuffer dest, int destPos, int length) {
- try {
- resource.copyInto(srcPos, dest, destPos, length);
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public void copyInto(int srcPos, Buffer destination, int destPos, int length) {
- if (!destination.isAccessible()) {
- throw new BufferClosedException("Destination buffer is closed");
- }
- if (destination.readOnly()) {
- throw new BufferReadOnlyException("Destination buffer is read only");
- }
-
- checkCopyIntoArgs(srcPos, length, destPos, destination.capacity());
-
- try {
- // Try to reduce bounds-checking by using larger primitives when possible.
- for (; length >= Long.BYTES; length -= Long.BYTES, srcPos += Long.BYTES, destPos += Long.BYTES) {
- destination.setLong(destPos, getLong(srcPos));
- }
- for (; length >= Integer.BYTES; length -= Integer.BYTES, srcPos += Integer.BYTES, destPos += Integer.BYTES) {
- destination.setInt(destPos, getInt(srcPos));
- }
- for (; length > 0; length--, srcPos++, destPos++) {
- destination.setByte(destPos, getByte(srcPos));
- }
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public Buffer copy(int offset, int length, boolean readOnly) {
- try {
- return new ProtonBufferToNetty5Adapter(resource.copy(offset, length));
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public Buffer split(int splitOffset) {
- try {
- return new ProtonBufferToNetty5Adapter(resource.split(splitOffset));
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public int bytesBefore(byte needle) {
- try {
- final int indexOf = resource.indexOf(needle);
- if (indexOf >= 0) {
- return indexOf - resource.getReadOffset();
- }
-
- return -1;
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public int bytesBefore(Buffer needle) {
- return InternalBufferUtils.bytesBefore(this, null, needle, null);
- }
-
- //----- Buffer input and output APIs
-
- @Override
- public int transferTo(WritableByteChannel channel, int length) throws IOException {
- try {
- return resource.transferTo(channel, length);
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public int transferFrom(FileChannel channel, long position, int length) throws IOException {
- try {
- return resource.transferFrom(channel, position, length);
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public int transferFrom(ReadableByteChannel channel, int length) throws IOException {
- try {
- return resource.transferFrom(channel, length);
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- //----- Buffer cursors API
-
- @Override
- public ByteCursor openCursor() {
- return openCursor(readerOffset(), readableBytes());
- }
-
- @Override
- public ByteCursor openCursor(int fromOffset, int length) {
- try {
- return new ProtonBufferToNetty5ByteCursor(resource.bufferIterator(fromOffset, length));
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- @Override
- public ByteCursor openReverseCursor(int fromOffset, int length) {
- try {
- return new ProtonBufferToNetty5ByteCursor(resource.bufferReverseIterator(fromOffset, length));
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- private final class ProtonBufferToNetty5ByteCursor implements ByteCursor {
-
- private final ProtonBufferIterator iterator;
-
- private byte lastReadByte = -1;
-
- public ProtonBufferToNetty5ByteCursor(ProtonBufferIterator iterator) {
- this.iterator = iterator;
- }
-
- @Override
- public boolean readByte() {
- if (iterator.hasNext()) {
- lastReadByte = iterator.next();
- return true;
- }
-
- return false;
- }
-
- @Override
- public byte getByte() {
- return lastReadByte;
- }
-
- @Override
- public int currentOffset() {
- return iterator.offset();
- }
-
- @Override
- public int bytesLeft() {
- return iterator.remaining();
- }
- }
-
- //----- Buffer components API
-
- @Override
- public int countComponents() {
- return resource.componentCount();
- }
-
- @Override
- public int countReadableComponents() {
- return resource.readableComponentCount();
- }
-
- @Override
- public int countWritableComponents() {
- return resource.writableComponentCount();
- }
-
- @Override
- public <T extends BufferComponent & Next> ComponentIterator<T> forEachComponent() {
- try {
- return new ProtonBufferComponentIterator<>(resource.componentAccessor());
- } catch (RuntimeException e) {
- throw translateToNettyException(e);
- }
- }
-
- //----- Primitive indexed set API
-
- @Override
- public Buffer setByte(int woff, byte value) {
- try {
- resource.setByte(woff, value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setUnsignedByte(int woff, int value) {
- try {
- resource.setByte(woff, (byte)(value & 0xFF));
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setChar(int woff, char value) {
- try {
- resource.setChar(woff, value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setShort(int woff, short value) {
- try {
- resource.setShort(woff, value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setUnsignedShort(int woff, int value) {
- try {
- resource.setUnsignedShort(woff, (short)(value & 0x0000FFFF));
- return null;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setMedium(int woff, int value) {
- try {
- resource.setByte(woff, (byte) (value >>> 16));
- resource.setByte(woff + 1, (byte) (value >>> 8));
- resource.setByte(woff + 2, (byte) (value >>> 0));
-
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setUnsignedMedium(int woff, int value) {
- try {
- resource.setByte(woff, (byte) (value >>> 16));
- resource.setByte(woff + 1, (byte) (value >>> 8));
- resource.setByte(woff + 2, (byte) (value >>> 0));
-
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setInt(int woff, int value) {
- try {
- resource.setInt(woff, value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setUnsignedInt(int woff, long value) {
- try {
- resource.setUnsignedInt(woff, (int)(value & 0x00000000FFFFFFFFl));
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setLong(int woff, long value) {
- try {
- resource.setLong(woff, value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setFloat(int woff, float value) {
- try {
- resource.setFloat(woff, value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer setDouble(int woff, double value) {
- try {
- resource.setDouble(woff, value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- //----- Primitive relative write API
-
- @Override
- public Buffer writeByte(byte value) {
- try {
- resource.writeByte(value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeUnsignedByte(int value) {
- try {
- resource.writeByte((byte) (value & 0xFF));
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeShort(short value) {
- try {
- resource.writeShort(value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeUnsignedShort(int value) {
- try {
- resource.writeShort((short) (value & 0x00FF));
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeChar(char value) {
- try {
- resource.writeChar(value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeMedium(int value) {
- try {
- resource.writeByte((byte) (value >>> 16));
- resource.writeByte((byte) (value >>> 8));
- resource.writeByte((byte) (value >>> 0));
-
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeUnsignedMedium(int value) {
- try {
- resource.writeByte((byte) (value >>> 16));
- resource.writeByte((byte) (value >>> 8));
- resource.writeByte((byte) (value >>> 0));
-
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeInt(int value) {
- try {
- resource.writeInt(value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeUnsignedInt(long value) {
- try {
- resource.writeInt((int)(value & 0x00000000FFFFFFFFl));
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeLong(long value) {
- try {
- resource.writeLong(value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeFloat(float value) {
- try {
- resource.writeFloat(value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeDouble(double value) {
- try {
- resource.writeDouble(value);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public Buffer writeCharSequence(CharSequence source, Charset charset) {
- try {
- resource.writeCharSequence(source, charset);
- return this;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- //----- Primitive indexed get API
-
- @Override
- public byte getByte(int index) {
- try {
- return resource.getByte(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public char getChar(int index) {
- try {
- return resource.getChar(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int getUnsignedByte(int index) {
- try {
- return resource.getUnsignedByte(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int getUnsignedShort(int index) {
- try {
- return resource.getUnsignedShort(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public short getShort(int index) {
- try {
- return resource.getShort(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int getMedium(int index) {
- try {
- return (getByte(index)) << 16 |
- (getByte(index + 1) & 0xFF) << 8 |
- (getByte(index + 2) & 0xFF) << 0;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int getUnsignedMedium(int index) {
- try {
- return ((getByte(index)) << 16 |
- (getByte(index + 1) & 0xFF) << 8 |
- (getByte(index + 2) & 0xFF) << 0) & 0xFFFFFF;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int getInt(int index) {
- try {
- return resource.getInt(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public long getUnsignedInt(int index) {
- try {
- return resource.getUnsignedInt(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public long getLong(int index) {
- try {
- return resource.getLong(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public float getFloat(int index) {
- try {
- return resource.getFloat(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public double getDouble(int index) {
- try {
- return resource.getDouble(index);
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- //----- Primitive relative read API
-
- @Override
- public byte readByte() {
- try {
- return resource.readByte();
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int readUnsignedByte() {
- try {
- return resource.readUnsignedByte();
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public char readChar() {
- try {
- return resource.readChar();
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public short readShort() {
- try {
- return resource.readShort();
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int readUnsignedShort() {
- try {
- return readShort() & 0x0000FFFF;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int readMedium() {
- try {
- return readByte() << 16 |
- (readByte() & 0xFF) << 8 |
- (readByte() & 0xFF) << 0;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int readUnsignedMedium() {
- try {
- return ((readByte()) << 16 |
- (readByte() & 0xFF) << 8 |
- (readByte() & 0xFF) << 0) & 0xFFFFFF;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public int readInt() {
- try {
- return resource.readInt();
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public long readUnsignedInt() {
- try {
- return readInt() & 0x00000000FFFFFFFFl;
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
-
- @Override
- public long readLong() {
- try {
- return resource.readLong();
- } catch (RuntimeException ex) {
- throw translateToNettyException(ex);
- }
- }
... 2060 lines suppressed ...
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org