[Git][java-team/jboss-xnio][master] 4 commits: New upstream version 3.8.0
Markus Koschany
gitlab at salsa.debian.org
Fri Mar 27 23:26:31 GMT 2020
Markus Koschany pushed to branch master at Debian Java Maintainers / jboss-xnio
Commits:
ac81ad05 by Markus Koschany at 2020-03-28T00:14:08+01:00
New upstream version 3.8.0
- - - - -
e23285d6 by Markus Koschany at 2020-03-28T00:14:13+01:00
Update upstream source from tag 'upstream/3.8.0'
Update to upstream version '3.8.0'
with Debian dir 7adf389be4bc4c14b8fcd1d768e170780ffefc89
- - - - -
c3f42a78 by Markus Koschany at 2020-03-28T00:15:09+01:00
Declare compliance with Debian Policy 4.5.0.
- - - - -
afe9826d by Markus Koschany at 2020-03-28T00:15:24+01:00
Update changelog
- - - - -
21 changed files:
- api/pom.xml
- api/src/main/java/org/xnio/ByteBufferSlicePool.java
- api/src/main/java/org/xnio/_private/Messages.java
- api/src/main/java/org/xnio/channels/Channels.java
- api/src/main/java/org/xnio/ssl/JsseSslConduitEngine.java
- api/src/main/java/org/xnio/ssl/JsseXnioSsl.java
- + api/src/test/java/org/xnio/channels/ChannelsBlockingFlushTestCase.java
- + api/src/test/java/org/xnio/channels/ChannelsBlockingTimeoutTimeoutTestCase.java
- debian/changelog
- debian/control
- nio-impl/pom.xml
- nio-impl/src/main/java/org/xnio/nio/NioXnio.java
- nio-impl/src/main/java/org/xnio/nio/NioXnioWorker.java
- − nio-impl/src/main/java/org/xnio/nio/QueuedNioTcpServer.java
- nio-impl/src/main/java/org/xnio/nio/QueuedNioTcpServerHandle.java → nio-impl/src/test/java/org/xnio/nio/test/AbstractNioSslBufferExpansionTcpTest.java
- nio-impl/src/test/java/org/xnio/nio/test/AbstractNioTcpTest.java
- + nio-impl/src/test/java/org/xnio/nio/test/NioSslBufferExpansionTcpChannelTestCase.java
- + nio-impl/src/test/java/org/xnio/nio/test/NioSslBufferExpansionTcpConnectionTestCase.java
- + nio-impl/src/test/java/org/xnio/nio/test/NioSslRandomlyTimedBufferExpansionTcpChannelTestCase.java
- + nio-impl/src/test/java/org/xnio/nio/test/NioSslRandomlyTimedBufferExpansionTcpConnectionTestCase.java
- pom.xml
Changes:
=====================================
api/pom.xml
=====================================
@@ -37,7 +37,7 @@
<parent>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-all</artifactId>
- <version>3.7.7.Final</version>
+ <version>3.8.0.Final</version>
</parent>
<dependencies>
=====================================
api/src/main/java/org/xnio/ByteBufferSlicePool.java
=====================================
@@ -155,15 +155,11 @@ public final class ByteBufferSlicePool implements Pool<ByteBuffer> {
// only true if using direct allocation
if (directBuffers != null) {
ByteBuffer region = FREE_DIRECT_BUFFERS.poll();
- try {
- if (region != null) {
- return sliceReusedBuffer(region, buffersPerRegion, bufferSize);
- }
- region = allocator.allocate(buffersPerRegion * bufferSize);
- return sliceAllocatedBuffer(region, buffersPerRegion, bufferSize);
- } finally {
- directBuffers.add(region);
+ if (region != null) {
+ return sliceReusedBuffer(region, buffersPerRegion, bufferSize);
}
+ region = allocator.allocate(buffersPerRegion * bufferSize);
+ return sliceAllocatedBuffer(region, buffersPerRegion, bufferSize);
}
return sliceAllocatedBuffer(
allocator.allocate(buffersPerRegion * bufferSize),
=====================================
api/src/main/java/org/xnio/_private/Messages.java
=====================================
@@ -240,6 +240,10 @@ public interface Messages extends BasicLogger {
@Message(id = 306, value = "SSL connection is not from this provider")
IllegalArgumentException notFromThisProvider();
+ @Message(id = 307, value = "Failed to close ssl engine when handling exception %s")
+ @LogMessage(level = WARN)
+ void failedToCloseSSLEngine(@Cause Throwable cause, Exception originalException);
+
// I/O errors
@Message(id = 800, value = "Read timed out")
@@ -353,4 +357,8 @@ public interface Messages extends BasicLogger {
@Message(value = "Shutting down reads on %s failed")
@LogMessage(level = TRACE)
void resourceReadShutdownFailed(@Cause Throwable cause, Object resource);
+
+ @Message(value = "Expanded buffer enabled due to overflow with empty buffer, expanded buffer size is %s")
+ @LogMessage(level = TRACE)
+ void expandedSslBufferEnabled(int bufferSize);
}
=====================================
api/src/main/java/org/xnio/channels/Channels.java
=====================================
@@ -65,6 +65,39 @@ public final class Channels {
}
}
+ /**
+ * Simple utility method to execute a blocking flush on a writable channel. The method blocks until there are no
+ * remaining bytes in the send queue or the timeout is reached.
+ *
+ * @param channel the writable channel
+ * @param time the amount of time to wait
+ * @param unit the unit of time to wait
+ * @return true if the channel was successfully flushed, false if the timeout was reached
+ * @throws IOException if an I/O exception occurs
+ *
+ * @since 3.8
+ */
+ public static boolean flushBlocking(SuspendableWriteChannel channel, long time, TimeUnit unit) throws IOException {
+ // In the fast path, the timeout is not used because bytes can be flushed without blocking.
+ if (channel.flush()) {
+ return true;
+ }
+ long remaining = unit.toNanos(time);
+ long now = System.nanoTime();
+ do {
+ // awaitWritable may return spuriously so looping is required.
+ channel.awaitWritable(remaining, TimeUnit.NANOSECONDS);
+ // flush prior to recalculating remaining time to avoid a nanoTime
+ // invocation in the optimal path.
+ if (channel.flush()) {
+ return true;
+ }
+ // Nanotime must only be used in comparison with another nanotime value
+ // This implementation allows us to avoid immediate subsequent nanoTime calls
+ } while ((remaining -= Math.max(-now + (now = System.nanoTime()), 0L)) > 0L);
+ return false;
+ }
+
/**
* Simple utility method to execute a blocking write shutdown on a writable channel. The method blocks until the
* channel's output side is fully shut down.
@@ -79,6 +112,23 @@ public final class Channels {
flushBlocking(channel);
}
+ /**
+ * Simple utility method to execute a blocking write shutdown on a writable channel. The method blocks until the
+ * channel's output side is fully shut down or the timeout is reached.
+ *
+ * @param channel the writable channel
+ * @param time the amount of time to wait
+ * @param unit the unit of time to wait
+ * @return true if the channel was successfully flushed, false if the timeout was reached
+ * @throws IOException if an I/O exception occurs
+ *
+ * @since 3.8
+ */
+ public static boolean shutdownWritesBlocking(SuspendableWriteChannel channel, long time, TimeUnit unit) throws IOException {
+ channel.shutdownWrites();
+ return flushBlocking(channel, time, unit);
+ }
+
/**
* Simple utility method to execute a blocking write on a byte channel. The method blocks until the bytes in the
* buffer have been fully written. To ensure that the data is sent, the {@link #flushBlocking(SuspendableWriteChannel)}
@@ -311,13 +361,27 @@ public final class Channels {
* @since 1.2
*/
public static <C extends ReadableByteChannel & SuspendableReadChannel> int readBlocking(C channel, ByteBuffer buffer, long time, TimeUnit unit) throws IOException {
+ // In the fast path, the timeout is not used because bytes can be read without blocking.
int res = channel.read(buffer);
- if (res == 0 && buffer.hasRemaining()) {
- channel.awaitReadable(time, unit);
- return channel.read(buffer);
- } else {
+ if (res != 0) {
return res;
}
+ long remaining = unit.toNanos(time);
+ long now = System.nanoTime();
+ while (buffer.hasRemaining() && remaining > 0) {
+ // awaitReadable may return spuriously, so looping is required.
+ channel.awaitReadable(remaining, TimeUnit.NANOSECONDS);
+ // read prior to recalculating remaining time to avoid a nanoTime
+ // invocation in the optimal path.
+ res = channel.read(buffer);
+ if (res != 0) {
+ return res;
+ }
+ // Nanotime must only be used in comparison with another nanotime value
+ // This implementation allows us to avoid immediate subsequent nanoTime calls
+ remaining -= Math.max(-now + (now = System.nanoTime()), 0L);
+ }
+ return res;
}
/**
@@ -357,13 +421,28 @@ public final class Channels {
* @since 1.2
*/
public static <C extends ScatteringByteChannel & SuspendableReadChannel> long readBlocking(C channel, ByteBuffer[] buffers, int offs, int len, long time, TimeUnit unit) throws IOException {
+ // In the fast path, the timeout is not used because bytes can be read
+ // without blocking or interaction with the precise clock.
long res = channel.read(buffers, offs, len);
- if (res == 0L && Buffers.hasRemaining(buffers, offs, len)) {
- channel.awaitReadable(time, unit);
- return channel.read(buffers, offs, len);
- } else {
+ if (res != 0L) {
return res;
}
+ long remaining = unit.toNanos(time);
+ long now = System.nanoTime();
+ while (Buffers.hasRemaining(buffers, offs, len) && remaining > 0) {
+ // awaitReadable may return spuriously, looping is required.
+ channel.awaitReadable(remaining, TimeUnit.NANOSECONDS);
+ // read prior to recalculating remaining time to avoid a nanoTime
+ // invocation in the optimal path.
+ res = channel.read(buffers, offs, len);
+ if (res != 0) {
+ return res;
+ }
+ // Nanotime must only be used in comparison with another nanotime value
+ // This implementation allows us to avoid immediate subsequent nanoTime calls
+ remaining -= Math.max(-now + (now = System.nanoTime()), 0L);
+ }
+ return res;
}
/**
@@ -399,13 +478,27 @@ public final class Channels {
* @since 1.2
*/
public static <C extends ReadableMessageChannel> int receiveBlocking(C channel, ByteBuffer buffer, long time, TimeUnit unit) throws IOException {
+ // In the fast path, the timeout is not used because bytes can be read without blocking.
int res = channel.receive(buffer);
- if ((res) == 0) {
- channel.awaitReadable(time, unit);
- return channel.receive(buffer);
- } else {
+ if (res != 0) {
return res;
}
+ long remaining = unit.toNanos(time);
+ long now = System.nanoTime();
+ while (buffer.hasRemaining() && remaining > 0) {
+ // awaitReadable may return spuriously, looping is required.
+ channel.awaitReadable(remaining, TimeUnit.NANOSECONDS);
+ // read prior to recalculating remaining time to avoid a nanoTime
+ // invocation in the optimal path.
+ res = channel.receive(buffer);
+ if (res != 0) {
+ return res;
+ }
+ // Nanotime must only be used in comparison with another nanotime value
+ // This implementation allows us to avoid immediate subsequent nanoTime calls
+ remaining -= Math.max(-now + (now = System.nanoTime()), 0L);
+ }
+ return res;
}
/**
@@ -445,13 +538,25 @@ public final class Channels {
* @since 1.2
*/
public static <C extends ReadableMessageChannel> long receiveBlocking(C channel, ByteBuffer[] buffers, int offs, int len, long time, TimeUnit unit) throws IOException {
+ // In the fast path, the timeout is not used because bytes can be read without blocking.
long res = channel.receive(buffers, offs, len);
- if ((res) == 0) {
- channel.awaitReadable(time, unit);
- return channel.receive(buffers, offs, len);
- } else {
+ if (res != 0L) {
return res;
}
+ long remaining = unit.toNanos(time);
+ long now = System.nanoTime();
+ while (Buffers.hasRemaining(buffers, offs, len) && remaining > 0) {
+ // awaitReadable may return spuriously, looping is required.
+ channel.awaitReadable(remaining, TimeUnit.NANOSECONDS);
+ res = channel.receive(buffers, offs, len);
+ if (res != 0) {
+ return res;
+ }
+ // Nanotime must only be used in comparison with another nanotime value
+ // This implementation allows us to avoid immediate subsequent nanoTime calls
+ remaining -= Math.max(-now + (now = System.nanoTime()), 0L);
+ }
+ return res;
}
/**
=====================================
api/src/main/java/org/xnio/ssl/JsseSslConduitEngine.java
=====================================
@@ -44,7 +44,10 @@ import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import org.jboss.logging.Logger;
+
+import org.xnio.BufferAllocator;
import org.xnio.Buffers;
+import org.xnio.ByteBufferSlicePool;
import org.xnio.Pool;
import org.xnio.Pooled;
import org.xnio.conduits.StreamSinkConduit;
@@ -86,6 +89,10 @@ final class JsseSslConduitEngine {
private final Pooled<ByteBuffer> receiveBuffer;
/** The buffer from which outbound SSL data is sent. */
private final Pooled<ByteBuffer> sendBuffer;
+ /** An expanded non-final buffer from which outbound SSL data is sent when
+ * large fragments handling is enabled in the underlying SSL Engine. When
+ * this happens, we need a specific buffer with expanded capacity. */
+ private ByteBuffer expandedSendBuffer;
/** The buffer into which inbound clear data is written. */
private final Pooled<ByteBuffer> readBuffer;
@@ -149,18 +156,11 @@ final class JsseSslConduitEngine {
sendBuffer = socketBufferPool.allocate();
try {
if (receiveBuffer.getResource().capacity() < packetBufferSize || sendBuffer.getResource().capacity() < packetBufferSize) {
- throw msg.socketBufferTooSmall();
+ // create expanded send buffer
+ expandedSendBuffer = ByteBuffer.allocate(packetBufferSize);
}
- final int applicationBufferSize = session.getApplicationBufferSize();
readBuffer = applicationBufferPool.allocate();
- try {
- if (readBuffer.getResource().capacity() < applicationBufferSize) {
- throw msg.appBufferTooSmall();
- }
- ok = true;
- } finally {
- if (! ok) readBuffer.free();
- }
+ ok = true;
} finally {
if (! ok) sendBuffer.free();
}
@@ -231,14 +231,13 @@ final class JsseSslConduitEngine {
// a workaround for a bug found in SSLEngine
throw new ClosedChannelException();
}
- final ByteBuffer buffer = sendBuffer.getResource();
long bytesConsumed = 0;
boolean run;
try {
do {
final SSLEngineResult result;
synchronized (getWrapLock()) {
- run = handleWrapResult(result = engineWrap(srcs, offset, length, buffer), false);
+ run = handleWrapResult(result = engineWrap(srcs, offset, length, getSendBuffer()), false);
bytesConsumed += (long) result.bytesConsumed();
}
// handshake will tell us whether to keep the loop
@@ -247,7 +246,7 @@ final class JsseSslConduitEngine {
} catch (SSLHandshakeException e) {
try {
synchronized (getWrapLock()) {
- engine.wrap(EMPTY_BUFFER, sendBuffer.getResource());
+ engine.wrap(EMPTY_BUFFER, getSendBuffer());
doFlush();
}
} catch (IOException ignore) {}
@@ -266,7 +265,7 @@ final class JsseSslConduitEngine {
public ByteBuffer getWrappedBuffer() {
assert Thread.holdsLock(getWrapLock());
assert ! Thread.holdsLock(getUnwrapLock());
- return allAreSet(stateUpdater.get(this), ENGINE_CLOSED)? Buffers.EMPTY_BYTE_BUFFER: sendBuffer.getResource();
+ return allAreSet(stateUpdater.get(this), ENGINE_CLOSED)? Buffers.EMPTY_BYTE_BUFFER: getSendBuffer();
}
/**
@@ -300,14 +299,13 @@ final class JsseSslConduitEngine {
throw new ClosedChannelException();
}
clearFlags(FIRST_HANDSHAKE);
- final ByteBuffer buffer = sendBuffer.getResource();
int bytesConsumed = 0;
boolean run;
try {
do {
final SSLEngineResult result;
synchronized (getWrapLock()) {
- run = handleWrapResult(result = engineWrap(src, buffer), isCloseExpected);
+ run = handleWrapResult(result = engineWrap(src, getSendBuffer()), isCloseExpected);
bytesConsumed += result.bytesConsumed();
}
// handshake will tell us whether to keep the loop
@@ -316,7 +314,7 @@ final class JsseSslConduitEngine {
} catch (SSLHandshakeException e) {
try {
synchronized (getWrapLock()) {
- engine.wrap(EMPTY_BUFFER, sendBuffer.getResource());
+ engine.wrap(EMPTY_BUFFER, getSendBuffer());
doFlush();
}
} catch (IOException ignore) {}
@@ -376,9 +374,13 @@ final class JsseSslConduitEngine {
case BUFFER_OVERFLOW: {
assert result.bytesConsumed() == 0;
assert result.bytesProduced() == 0;
- final ByteBuffer buffer = sendBuffer.getResource();
+ final ByteBuffer buffer = getSendBuffer();
if (buffer.position() == 0) {
- throw msg.wrongBufferExpansion();
+ final int bufferSize = engine.getSession().getPacketBufferSize();
+ if (buffer.capacity() < bufferSize) {
+ msg.expandedSslBufferEnabled(bufferSize);
+ expandedSendBuffer = ByteBuffer.allocate(bufferSize);
+ } else throw msg.wrongBufferExpansion();
} else {
// there's some data in there, so send it first
buffer.flip();
@@ -462,7 +464,7 @@ final class JsseSslConduitEngine {
if (write) {
return true;
}
- final ByteBuffer buffer = sendBuffer.getResource();
+ final ByteBuffer buffer = getSendBuffer();
// else, trigger a write call
// Needs wrap, so we wrap (if possible)...
synchronized (getWrapLock()) {
@@ -578,6 +580,8 @@ final class JsseSslConduitEngine {
return (int) unwrap(new ByteBuffer[]{dst}, 0, 1);
}
+ private int failureCount = 0;
+
/**
* Unwraps the bytes contained in {@link #getUnwrapBuffer()}, copying the resulting unwrapped bytes into
* {@code dsts}.
@@ -632,7 +636,7 @@ final class JsseSslConduitEngine {
} catch (SSLHandshakeException e) {
try {
synchronized (getWrapLock()) {
- engine.wrap(EMPTY_BUFFER, sendBuffer.getResource());
+ engine.wrap(EMPTY_BUFFER, getSendBuffer());
doFlush();
}
} catch (IOException ignore) {}
@@ -827,15 +831,14 @@ final class JsseSslConduitEngine {
if (sinkConduit.isWriteShutdown()) {
return true;
}
- final ByteBuffer buffer = sendBuffer.getResource();
if (!engine.isOutboundDone() || !engine.isInboundDone()) {
SSLEngineResult result;
do {
- if (!handleWrapResult(result = engineWrap(Buffers.EMPTY_BYTE_BUFFER, buffer), true)) {
+ if (!handleWrapResult(result = engineWrap(Buffers.EMPTY_BYTE_BUFFER, getSendBuffer()), true)) {
return false;
}
} while (handleHandshake(result, true) && (result.getHandshakeStatus() != HandshakeStatus.NEED_UNWRAP || !engine.isOutboundDone()));
- handleWrapResult(result = engineWrap(Buffers.EMPTY_BYTE_BUFFER, buffer), true);
+ handleWrapResult(result = engineWrap(Buffers.EMPTY_BYTE_BUFFER, getSendBuffer()), true);
if (!engine.isOutboundDone() || (result.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING &&
result.getHandshakeStatus() != HandshakeStatus.NEED_UNWRAP)) {
return false;
@@ -855,7 +858,7 @@ final class JsseSslConduitEngine {
assert Thread.holdsLock(getWrapLock());
assert ! Thread.holdsLock(getUnwrapLock());
final ByteBuffer buffer;
- buffer = sendBuffer.getResource();
+ buffer = getSendBuffer();
buffer.flip();
try {
while (buffer.hasRemaining()) {
@@ -914,9 +917,13 @@ final class JsseSslConduitEngine {
}
} catch (Exception e) {
//if there is an exception on close we immediately close the engine to make sure buffers are freed
- closeEngine();
+ try {
+ closeEngine();
+ } catch (Exception closeEngineException) {
+ msg.failedToCloseSSLEngine(e, closeEngineException);
+ }
if(e instanceof IOException) {
- throw (IOException)e;
+ throw (IOException) e;
} else {
throw (RuntimeException)e;
}
@@ -1197,4 +1204,8 @@ final class JsseSslConduitEngine {
}
}
}
+
+ private final ByteBuffer getSendBuffer() {
+ return expandedSendBuffer != null? expandedSendBuffer : sendBuffer.getResource();
+ }
}
=====================================
api/src/main/java/org/xnio/ssl/JsseXnioSsl.java
=====================================
@@ -159,7 +159,13 @@ public final class JsseXnioSsl extends XnioSsl {
public void handleEvent(final StreamConnection connection) {
final SSLEngine sslEngine = JsseSslUtils.createSSLEngine(sslContext, optionMap, destination);
final boolean startTls = optionMap.get(Options.SSL_STARTTLS, false);
- final SslConnection wrappedConnection = NEW_IMPL ? new JsseSslConnection(connection, sslEngine, bufferPool, bufferPool) : new JsseSslStreamConnection(connection, sslEngine, bufferPool, bufferPool, startTls);
+ final SslConnection wrappedConnection;
+ try {
+ wrappedConnection = NEW_IMPL ? new JsseSslConnection(connection, sslEngine, bufferPool, bufferPool) : new JsseSslStreamConnection(connection, sslEngine, bufferPool, bufferPool, startTls);
+ } catch (RuntimeException e) {
+ futureResult.setCancelled();
+ throw e;
+ }
if (NEW_IMPL && ! startTls) {
try {
wrappedConnection.startHandshake();
=====================================
api/src/test/java/org/xnio/channels/ChannelsBlockingFlushTestCase.java
=====================================
@@ -0,0 +1,150 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2020 Red Hat, Inc. and/or its affiliates, and individual
+ * contributors as indicated by the @author tags.
+ *
+ * Licensed 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.xnio.channels;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+
+/**
+ * Test for {@link Channels} blocking flush operations with timeouts.
+ *
+ * @author Carter Kozak
+ */
+public class ChannelsBlockingFlushTestCase {
+
+ @Test
+ public void testFlushBlockingSpuriousReturn() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ SuspendableWriteChannel stubChannel = (SuspendableWriteChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{SuspendableWriteChannel.class},
+ new InvocationHandler() {
+ int flushes = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("flush".equals(method.getName())) {
+ return flushes++ > 1;
+ } else if ("awaitWritable".equals(method.getName())) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ assertTrue(Channels.flushBlocking(stubChannel,1, TimeUnit.SECONDS));
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("flush", "awaitWritable", "flush", "awaitWritable", "flush"), invocations);
+ }
+
+ @Test
+ public void testFlushBlockingTimeout() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ SuspendableWriteChannel stubChannel = (SuspendableWriteChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{SuspendableWriteChannel.class},
+ new InvocationHandler() {
+ int flushes = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("flush".equals(method.getName())) {
+ return flushes++ > 1;
+ } else if ("awaitWritable".equals(method.getName())) {
+ // Sleep twenty milliseconds, which exceeds our ten millisecond timeout
+ Thread.sleep(20);
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ assertFalse(Channels.flushBlocking(stubChannel,10, TimeUnit.MILLISECONDS));
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("flush", "awaitWritable", "flush"), invocations);
+ }
+
+ @Test
+ public void testShutdownWritesBlockingSpuriousReturn() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ SuspendableWriteChannel stubChannel = (SuspendableWriteChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{SuspendableWriteChannel.class},
+ new InvocationHandler() {
+ int flushes = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("flush".equals(method.getName())) {
+ return flushes++ > 1;
+ } else if ("awaitWritable".equals(method.getName())) {
+ return null;
+ } else if ("shutdownWrites".equals(method.getName())) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ assertTrue(Channels.shutdownWritesBlocking(stubChannel,1, TimeUnit.SECONDS));
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("shutdownWrites", "flush", "awaitWritable", "flush", "awaitWritable", "flush"), invocations);
+ }
+
+ @Test
+ public void testShutdownWritesBlockingTimeout() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ SuspendableWriteChannel stubChannel = (SuspendableWriteChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{SuspendableWriteChannel.class},
+ new InvocationHandler() {
+ int flushes = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("flush".equals(method.getName())) {
+ return flushes++ > 1;
+ } else if ("awaitWritable".equals(method.getName())) {
+ // Sleep twenty milliseconds, which exceeds our ten millisecond timeout
+ Thread.sleep(20);
+ return null;
+ } else if ("shutdownWrites".equals(method.getName())) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ assertFalse(Channels.shutdownWritesBlocking(stubChannel,10, TimeUnit.MILLISECONDS));
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("shutdownWrites", "flush", "awaitWritable", "flush"), invocations);
+ }
+}
=====================================
api/src/test/java/org/xnio/channels/ChannelsBlockingTimeoutTimeoutTestCase.java
=====================================
@@ -0,0 +1,284 @@
+package org.xnio.channels;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ScatteringByteChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for {@link Channels} blocking operations with timeouts.
+ *
+ * @author Carter Kozak
+ */
+public class ChannelsBlockingTimeoutTimeoutTestCase {
+
+ @Test
+ public void testSingleBufferReadBlockingSpuriousReturn() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("read".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ int result = Channels.readBlocking(stubChannel, ByteBuffer.allocate(32), 1, TimeUnit.SECONDS);
+ assertEquals(1, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("read", "awaitReadable", "read", "awaitReadable", "read"), invocations);
+ }
+
+ @Test
+ public void testSingleBufferReadBlockingSpuriousReturnReachesTimeout() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("read".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ // Sleep twenty milliseconds, which exceeds our ten millisecond timeout
+ Thread.sleep(20);
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ // Note, use ten milliseconds to avoid issues on platforms with coarse clocks
+ int result = Channels.readBlocking(stubChannel, ByteBuffer.allocate(32), 10, TimeUnit.MILLISECONDS);
+ assertEquals(0, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("read", "awaitReadable", "read"), invocations);
+ }
+
+ @Test
+ public void testMultiBufferReadBlockingSpuriousReturn() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("read".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0L;
+ } else {
+ return 1L;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ long result = Channels.readBlocking(stubChannel, new ByteBuffer[] {ByteBuffer.allocate(32)}, 0, 10, 1, TimeUnit.SECONDS);
+ assertEquals(1L, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("read", "awaitReadable", "read", "awaitReadable", "read"), invocations);
+ }
+
+ @Test
+ public void testMultiBufferReadBlockingSpuriousReturnReachesTimeout() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("read".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0L;
+ } else {
+ return 1L;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ // Sleep twenty milliseconds, which exceeds our ten millisecond timeout
+ Thread.sleep(20);
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ // Note, use ten milliseconds to avoid issues on platforms with coarse clocks
+ long result = Channels.readBlocking(stubChannel, new ByteBuffer[] {ByteBuffer.allocate(32)}, 0, 10, 10, TimeUnit.MILLISECONDS);
+ assertEquals(0L, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("read", "awaitReadable", "read"), invocations);
+ }
+
+ // here
+
+ @Test
+ public void testSingleBufferReceiveBlockingSpuriousReturn() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("receive".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ int result = Channels.receiveBlocking(stubChannel, ByteBuffer.allocate(32), 1, TimeUnit.SECONDS);
+ assertEquals(1, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("receive", "awaitReadable", "receive", "awaitReadable", "receive"), invocations);
+ }
+
+ @Test
+ public void testSingleBufferReceiveBlockingSpuriousReturnReachesTimeout() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("receive".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ // Sleep twenty milliseconds, which exceeds our ten millisecond timeout
+ Thread.sleep(20);
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ // Note, use ten milliseconds to avoid issues on platforms with coarse clocks
+ int result = Channels.receiveBlocking(stubChannel, ByteBuffer.allocate(32), 10, TimeUnit.MILLISECONDS);
+ assertEquals(0, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("receive", "awaitReadable", "receive"), invocations);
+ }
+
+ @Test
+ public void testMultiBufferReceiveBlockingSpuriousReturn() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("receive".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0L;
+ } else {
+ return 1L;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ long result = Channels.receiveBlocking(stubChannel, new ByteBuffer[] {ByteBuffer.allocate(32)}, 0, 10, 1, TimeUnit.SECONDS);
+ assertEquals(1L, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("receive", "awaitReadable", "receive", "awaitReadable", "receive"), invocations);
+ }
+
+ @Test
+ public void testMultiBufferReceiveBlockingSpuriousReturnReachesTimeout() throws IOException {
+ List<String> invocations = new ArrayList<String>();
+ ReadableSuspendableChannel stubChannel = (ReadableSuspendableChannel) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class<?>[]{ReadableSuspendableChannel.class},
+ new InvocationHandler() {
+ int reads = 0;
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ invocations.add(method.getName());
+ if ("receive".equals(method.getName())) {
+ if (reads++ <= 1) {
+ return 0L;
+ } else {
+ return 1L;
+ }
+ } else if ("awaitReadable".equals(method.getName())) {
+ // Sleep twenty milliseconds, which exceeds our ten millisecond timeout
+ Thread.sleep(20);
+ return null;
+ }
+ throw new IllegalStateException("Unexpected method invocation: "
+ + method + " with args " + Arrays.toString(args));
+ }
+ });
+ // Note, use ten milliseconds to avoid issues on platforms with coarse clocks
+ long result = Channels.receiveBlocking(stubChannel, new ByteBuffer[] {ByteBuffer.allocate(32)}, 0, 10, 10, TimeUnit.MILLISECONDS);
+ assertEquals(0L, result);
+ // Validate that awaitReadable was called multiple times, and is always followed by a read.
+ assertEquals(Arrays.asList("receive", "awaitReadable", "receive"), invocations);
+ }
+
+ interface ReadableSuspendableChannel
+ extends ReadableByteChannel, SuspendableReadChannel, ScatteringByteChannel, ReadableMessageChannel {
+
+ }
+}
=====================================
debian/changelog
=====================================
@@ -1,3 +1,10 @@
+jboss-xnio (3.8.0-1) unstable; urgency=medium
+
+ * New upstream version 3.8.0.
+ * Declare compliance with Debian Policy 4.5.0.
+
+ -- Markus Koschany <apo at debian.org> Sat, 28 Mar 2020 00:15:15 +0100
+
jboss-xnio (3.7.7-1) unstable; urgency=medium
* New upstream version 3.7.7.
=====================================
debian/control
=====================================
@@ -20,7 +20,7 @@ Build-Depends:
libwildfly-client-config-java,
libwildfly-common-java,
maven-debian-helper (>= 1.5)
-Standards-Version: 4.4.1
+Standards-Version: 4.5.0
Vcs-Git: https://salsa.debian.org/java-team/jboss-xnio.git
Vcs-Browser: https://salsa.debian.org/java-team/jboss-xnio
Homepage: http://xnio.jboss.org/
=====================================
nio-impl/pom.xml
=====================================
@@ -31,7 +31,7 @@
<parent>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-all</artifactId>
- <version>3.7.7.Final</version>
+ <version>3.8.0.Final</version>
</parent>
<properties>
@@ -164,6 +164,7 @@
<enableAssertions>true</enableAssertions>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<trimStackTrace>false</trimStackTrace>
+ <reuseForks>false</reuseForks>
</configuration>
</plugin>
<plugin>
=====================================
nio-impl/src/main/java/org/xnio/nio/NioXnio.java
=====================================
@@ -47,7 +47,6 @@ final class NioXnio extends Xnio {
static final boolean IS_HP_UX;
static final boolean HAS_BUGGY_EVENT_PORT;
- static final boolean USE_ALT_QUEUED_SERVER;
interface SelectorCreator {
Selector open() throws IOException;
@@ -65,7 +64,6 @@ final class NioXnio extends Xnio {
return Boolean.valueOf(System.getProperty("os.name", "unknown").equalsIgnoreCase("hp-ux"));
}
}).booleanValue();
- USE_ALT_QUEUED_SERVER = Boolean.parseBoolean(AccessController.doPrivileged(new ReadPropertyAction("xnio.nio.alt-queued-server", "true")));
// if a JDK is released with a fix, we can try to detect it and set this to "false" for those JDKs.
HAS_BUGGY_EVENT_PORT = true;
}
=====================================
nio-impl/src/main/java/org/xnio/nio/NioXnioWorker.java
=====================================
@@ -184,13 +184,8 @@ final class NioXnioWorker extends XnioWorker {
server.setAcceptListener(acceptListener);
ok = true;
return server;
- } else if (NioXnio.USE_ALT_QUEUED_SERVER) {
- final QueuedNioTcpServer2 server = new QueuedNioTcpServer2(new NioTcpServer(this, channel, optionMap, true));
- server.setAcceptListener(acceptListener);
- ok = true;
- return server;
} else {
- final QueuedNioTcpServer server = new QueuedNioTcpServer(this, channel, optionMap);
+ final QueuedNioTcpServer2 server = new QueuedNioTcpServer2(new NioTcpServer(this, channel, optionMap, true));
server.setAcceptListener(acceptListener);
ok = true;
return server;
=====================================
nio-impl/src/main/java/org/xnio/nio/QueuedNioTcpServer.java deleted
=====================================
@@ -1,535 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Copyright 2015 Red Hat, Inc. and/or its affiliates.
- *
- * Licensed 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.xnio.nio;
-
-import static org.xnio.IoUtils.safeClose;
-import static org.xnio.nio.Log.log;
-import static org.xnio.nio.Log.tcpServerConnectionLimitLog;
-import static org.xnio.nio.Log.tcpServerLog;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.nio.channels.ClosedChannelException;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.ServerSocketChannel;
-import java.nio.channels.SocketChannel;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
-import java.util.concurrent.atomic.AtomicLongFieldUpdater;
-
-import org.jboss.logging.Logger;
-import org.xnio.ChannelListener;
-import org.xnio.ChannelListeners;
-import org.xnio.ManagementRegistration;
-import org.xnio.IoUtils;
-import org.xnio.LocalSocketAddress;
-import org.xnio.Option;
-import org.xnio.OptionMap;
-import org.xnio.Options;
-import org.xnio.StreamConnection;
-import org.xnio.XnioExecutor;
-import org.xnio.channels.AcceptListenerSettable;
-import org.xnio.channels.AcceptingChannel;
-import org.xnio.channels.UnsupportedOptionException;
-import org.xnio.management.XnioServerMXBean;
-
-final class QueuedNioTcpServer extends AbstractNioChannel<QueuedNioTcpServer> implements AcceptingChannel<StreamConnection>, AcceptListenerSettable<QueuedNioTcpServer> {
- private static final String FQCN = QueuedNioTcpServer.class.getName();
-
- private volatile ChannelListener<? super QueuedNioTcpServer> acceptListener;
-
- private final QueuedNioTcpServerHandle handle;
- private final WorkerThread thread;
-
- private final ServerSocketChannel channel;
- private final ServerSocket socket;
- private final ManagementRegistration mbeanHandle;
-
- private final List<BlockingQueue<SocketChannel>> acceptQueues;
-
- private static final Set<Option<?>> options = Option.setBuilder()
- .add(Options.REUSE_ADDRESSES)
- .add(Options.RECEIVE_BUFFER)
- .add(Options.SEND_BUFFER)
- .add(Options.KEEP_ALIVE)
- .add(Options.TCP_OOB_INLINE)
- .add(Options.TCP_NODELAY)
- .add(Options.CONNECTION_HIGH_WATER)
- .add(Options.CONNECTION_LOW_WATER)
- .add(Options.READ_TIMEOUT)
- .add(Options.WRITE_TIMEOUT)
- .create();
-
- @SuppressWarnings("unused")
- private volatile int keepAlive;
- @SuppressWarnings("unused")
- private volatile int oobInline;
- @SuppressWarnings("unused")
- private volatile int tcpNoDelay;
- @SuppressWarnings("unused")
- private volatile int sendBuffer = -1;
- @SuppressWarnings("unused")
- private volatile long connectionStatus = CONN_LOW_MASK | CONN_HIGH_MASK;
- @SuppressWarnings("unused")
- private volatile int readTimeout;
- @SuppressWarnings("unused")
- private volatile int writeTimeout;
-
- private static final long CONN_LOW_MASK = 0x000000007FFFFFFFL;
- private static final long CONN_LOW_BIT = 0L;
- @SuppressWarnings("unused")
- private static final long CONN_LOW_ONE = 1L;
- private static final long CONN_HIGH_MASK = 0x3FFFFFFF80000000L;
- private static final long CONN_HIGH_BIT = 31L;
- @SuppressWarnings("unused")
- private static final long CONN_HIGH_ONE = 1L << CONN_HIGH_BIT;
-
- /**
- * The current number of open connections, can only be accessed by the accept thread
- */
- private int openConnections;
- private boolean limitwarn = true;
- private volatile boolean suspendedDueToWatermark;
- private volatile boolean suspended;
-
- private static final AtomicIntegerFieldUpdater<QueuedNioTcpServer> keepAliveUpdater = AtomicIntegerFieldUpdater.newUpdater(QueuedNioTcpServer.class, "keepAlive");
- private static final AtomicIntegerFieldUpdater<QueuedNioTcpServer> oobInlineUpdater = AtomicIntegerFieldUpdater.newUpdater(QueuedNioTcpServer.class, "oobInline");
- private static final AtomicIntegerFieldUpdater<QueuedNioTcpServer> tcpNoDelayUpdater = AtomicIntegerFieldUpdater.newUpdater(QueuedNioTcpServer.class, "tcpNoDelay");
- private static final AtomicIntegerFieldUpdater<QueuedNioTcpServer> sendBufferUpdater = AtomicIntegerFieldUpdater.newUpdater(QueuedNioTcpServer.class, "sendBuffer");
- private static final AtomicIntegerFieldUpdater<QueuedNioTcpServer> readTimeoutUpdater = AtomicIntegerFieldUpdater.newUpdater(QueuedNioTcpServer.class, "readTimeout");
- private static final AtomicIntegerFieldUpdater<QueuedNioTcpServer> writeTimeoutUpdater = AtomicIntegerFieldUpdater.newUpdater(QueuedNioTcpServer.class, "writeTimeout");
-
- private static final AtomicLongFieldUpdater<QueuedNioTcpServer> connectionStatusUpdater = AtomicLongFieldUpdater.newUpdater(QueuedNioTcpServer.class, "connectionStatus");
- private final Runnable acceptTask = new Runnable() {
- public void run() {
- final WorkerThread current = WorkerThread.getCurrent();
- assert current != null;
- final BlockingQueue<SocketChannel> queue = acceptQueues.get(current.getNumber());
- ChannelListeners.invokeChannelListener(QueuedNioTcpServer.this, getAcceptListener());
- if (! queue.isEmpty() && !suspendedDueToWatermark) {
- current.execute(this);
- }
- }
- };
-
- private final Runnable connectionClosedTask = new Runnable() {
- @Override
- public void run() {
- openConnections--;
- if(suspendedDueToWatermark && openConnections < getLowWater(connectionStatus)) {
- synchronized (QueuedNioTcpServer.this) {
- suspendedDueToWatermark = false;
- }
- }
- }
- };
-
- QueuedNioTcpServer(final NioXnioWorker worker, final ServerSocketChannel channel, final OptionMap optionMap) throws IOException {
- super(worker);
- this.channel = channel;
- this.thread = worker.getAcceptThread();
- final WorkerThread[] workerThreads = worker.getAll();
- final List<BlockingQueue<SocketChannel>> acceptQueues = new ArrayList<>(workerThreads.length);
- for (int i = 0; i < workerThreads.length; i++) {
- acceptQueues.add(i, new LinkedBlockingQueue<SocketChannel>());
- }
- this.acceptQueues = acceptQueues;
- socket = channel.socket();
- if (optionMap.contains(Options.SEND_BUFFER)) {
- final int sendBufferSize = optionMap.get(Options.SEND_BUFFER, DEFAULT_BUFFER_SIZE);
- if (sendBufferSize < 1) {
- throw log.parameterOutOfRange("sendBufferSize");
- }
- sendBufferUpdater.set(this, sendBufferSize);
- }
- if (optionMap.contains(Options.KEEP_ALIVE)) {
- keepAliveUpdater.lazySet(this, optionMap.get(Options.KEEP_ALIVE, false) ? 1 : 0);
- }
- if (optionMap.contains(Options.TCP_OOB_INLINE)) {
- oobInlineUpdater.lazySet(this, optionMap.get(Options.TCP_OOB_INLINE, false) ? 1 : 0);
- }
- if (optionMap.contains(Options.TCP_NODELAY)) {
- tcpNoDelayUpdater.lazySet(this, optionMap.get(Options.TCP_NODELAY, false) ? 1 : 0);
- }
- if (optionMap.contains(Options.READ_TIMEOUT)) {
- readTimeoutUpdater.lazySet(this, optionMap.get(Options.READ_TIMEOUT, 0));
- }
- if (optionMap.contains(Options.WRITE_TIMEOUT)) {
- writeTimeoutUpdater.lazySet(this, optionMap.get(Options.WRITE_TIMEOUT, 0));
- }
- final int highWater;
- final int lowWater;
- if (optionMap.contains(Options.CONNECTION_HIGH_WATER) || optionMap.contains(Options.CONNECTION_LOW_WATER)) {
- highWater = optionMap.get(Options.CONNECTION_HIGH_WATER, Integer.MAX_VALUE);
- lowWater = optionMap.get(Options.CONNECTION_LOW_WATER, highWater);
- if (highWater <= 0) {
- throw badHighWater();
- }
- if (lowWater <= 0 || lowWater > highWater) {
- throw badLowWater(highWater);
- }
- final long highLowWater = (long) highWater << CONN_HIGH_BIT | (long) lowWater << CONN_LOW_BIT;
- connectionStatusUpdater.lazySet(this, highLowWater);
- } else {
- highWater = Integer.MAX_VALUE;
- lowWater = Integer.MAX_VALUE;
- connectionStatusUpdater.lazySet(this, CONN_LOW_MASK | CONN_HIGH_MASK);
- }
- final SelectionKey key = thread.registerChannel(channel);
- handle = new QueuedNioTcpServerHandle(this, thread, key, highWater, lowWater);
- key.attach(handle);
- mbeanHandle = worker.registerServerMXBean(
- new XnioServerMXBean() {
- public String getProviderName() {
- return "nio";
- }
-
- public String getWorkerName() {
- return worker.getName();
- }
-
- public String getBindAddress() {
- return String.valueOf(getLocalAddress());
- }
-
- public int getConnectionCount() {
- CompletableFuture<Integer> future = CompletableFuture.supplyAsync(
- () -> openConnections, handle.getWorkerThread()
- );
- try {
- return future.get();
- } catch (InterruptedException | ExecutionException e) {
- return -1;
- }
- }
-
- public int getConnectionLimitHighWater() {
- return getHighWater(connectionStatus);
- }
-
- public int getConnectionLimitLowWater() {
- return getLowWater(connectionStatus);
- }
- });
- }
-
- private static IllegalArgumentException badLowWater(final int highWater) {
- return new IllegalArgumentException("Low water must be greater than 0 and less than or equal to high water (" + highWater + ")");
- }
-
- private static IllegalArgumentException badHighWater() {
- return new IllegalArgumentException("High water must be greater than 0");
- }
-
- public void close() throws IOException {
- try {
- channel.close();
- } finally {
- handle.cancelKey(true);
- safeClose(mbeanHandle);
- }
- }
-
- public boolean supportsOption(final Option<?> option) {
- return options.contains(option);
- }
-
- public <T> T getOption(final Option<T> option) throws UnsupportedOptionException, IOException {
- if (option == Options.REUSE_ADDRESSES) {
- return option.cast(Boolean.valueOf(socket.getReuseAddress()));
- } else if (option == Options.RECEIVE_BUFFER) {
- return option.cast(Integer.valueOf(socket.getReceiveBufferSize()));
- } else if (option == Options.SEND_BUFFER) {
- final int value = sendBuffer;
- return value == -1 ? null : option.cast(Integer.valueOf(value));
- } else if (option == Options.KEEP_ALIVE) {
- return option.cast(Boolean.valueOf(keepAlive != 0));
- } else if (option == Options.TCP_OOB_INLINE) {
- return option.cast(Boolean.valueOf(oobInline != 0));
- } else if (option == Options.TCP_NODELAY) {
- return option.cast(Boolean.valueOf(tcpNoDelay != 0));
- } else if (option == Options.READ_TIMEOUT) {
- return option.cast(Integer.valueOf(readTimeout));
- } else if (option == Options.WRITE_TIMEOUT) {
- return option.cast(Integer.valueOf(writeTimeout));
- } else if (option == Options.CONNECTION_HIGH_WATER) {
- return option.cast(Integer.valueOf(getHighWater(connectionStatus)));
- } else if (option == Options.CONNECTION_LOW_WATER) {
- return option.cast(Integer.valueOf(getLowWater(connectionStatus)));
- } else {
- return null;
- }
- }
-
- public <T> T setOption(final Option<T> option, final T value) throws IllegalArgumentException, IOException {
- final Object old;
- if (option == Options.REUSE_ADDRESSES) {
- old = Boolean.valueOf(socket.getReuseAddress());
- socket.setReuseAddress(Options.REUSE_ADDRESSES.cast(value, Boolean.FALSE).booleanValue());
- } else if (option == Options.RECEIVE_BUFFER) {
- old = Integer.valueOf(socket.getReceiveBufferSize());
- final int newValue = Options.RECEIVE_BUFFER.cast(value, Integer.valueOf(DEFAULT_BUFFER_SIZE)).intValue();
- if (newValue < 1) {
- throw log.optionOutOfRange("RECEIVE_BUFFER");
- }
- socket.setReceiveBufferSize(newValue);
- } else if (option == Options.SEND_BUFFER) {
- final int newValue = Options.SEND_BUFFER.cast(value, Integer.valueOf(DEFAULT_BUFFER_SIZE)).intValue();
- if (newValue < 1) {
- throw log.optionOutOfRange("SEND_BUFFER");
- }
- final int oldValue = sendBufferUpdater.getAndSet(this, newValue);
- old = oldValue == -1 ? null : Integer.valueOf(oldValue);
- } else if (option == Options.KEEP_ALIVE) {
- old = Boolean.valueOf(keepAliveUpdater.getAndSet(this, Options.KEEP_ALIVE.cast(value, Boolean.FALSE).booleanValue() ? 1 : 0) != 0);
- } else if (option == Options.TCP_OOB_INLINE) {
- old = Boolean.valueOf(oobInlineUpdater.getAndSet(this, Options.TCP_OOB_INLINE.cast(value, Boolean.FALSE).booleanValue() ? 1 : 0) != 0);
- } else if (option == Options.TCP_NODELAY) {
- old = Boolean.valueOf(tcpNoDelayUpdater.getAndSet(this, Options.TCP_NODELAY.cast(value, Boolean.FALSE).booleanValue() ? 1 : 0) != 0);
- } else if (option == Options.READ_TIMEOUT) {
- old = Integer.valueOf(readTimeoutUpdater.getAndSet(this, Options.READ_TIMEOUT.cast(value, Integer.valueOf(0)).intValue()));
- } else if (option == Options.WRITE_TIMEOUT) {
- old = Integer.valueOf(writeTimeoutUpdater.getAndSet(this, Options.WRITE_TIMEOUT.cast(value, Integer.valueOf(0)).intValue()));
- } else if (option == Options.CONNECTION_HIGH_WATER) {
- old = Integer.valueOf(getHighWater(updateWaterMark(-1, Options.CONNECTION_HIGH_WATER.cast(value, Integer.valueOf(Integer.MAX_VALUE)).intValue())));
- } else if (option == Options.CONNECTION_LOW_WATER) {
- old = Integer.valueOf(getLowWater(updateWaterMark(Options.CONNECTION_LOW_WATER.cast(value, Integer.valueOf(Integer.MAX_VALUE)).intValue(), -1)));
- } else {
- return null;
- }
- return option.cast(old);
- }
-
- private long updateWaterMark(int reqNewLowWater, int reqNewHighWater) {
- // at least one must be specified
- assert reqNewLowWater != -1 || reqNewHighWater != -1;
- // if both given, low must be less than high
- assert reqNewLowWater == -1 || reqNewHighWater == -1 || reqNewLowWater <= reqNewHighWater;
-
- long oldVal, newVal;
- int oldHighWater, oldLowWater;
- int newLowWater, newHighWater;
-
- do {
- oldVal = connectionStatus;
- oldLowWater = getLowWater(oldVal);
- oldHighWater = getHighWater(oldVal);
- newLowWater = reqNewLowWater == -1 ? oldLowWater : reqNewLowWater;
- newHighWater = reqNewHighWater == -1 ? oldHighWater : reqNewHighWater;
- // Make sure the new values make sense
- if (reqNewLowWater != -1 && newLowWater > newHighWater) {
- newHighWater = newLowWater;
- } else if (reqNewHighWater != -1 && newHighWater < newLowWater) {
- newLowWater = newHighWater;
- }
- // See if the change would be redundant
- if (oldLowWater == newLowWater && oldHighWater == newHighWater) {
- return oldVal;
- }
- newVal = (long)newLowWater << CONN_LOW_BIT | (long)newHighWater << CONN_HIGH_BIT;
- } while (! connectionStatusUpdater.compareAndSet(this, oldVal, newVal));
- getIoThread().execute(new Runnable() {
- @Override
- public void run() {
- if(openConnections >= getHighWater(connectionStatus)) {
- synchronized (QueuedNioTcpServer.this) {
- suspendedDueToWatermark = true;
- tcpServerConnectionLimitLog.logf(FQCN, Logger.Level.DEBUG, null, "Total open connections reach high water limit (%s) after updating water mark", getHighWater(connectionStatus));
- }
- } else if(suspendedDueToWatermark && openConnections <= getLowWater(connectionStatus)) {
- suspendedDueToWatermark = false;
- }
- }
- });
- return oldVal;
- }
-
- private static int getHighWater(final long value) {
- return (int) ((value & CONN_HIGH_MASK) >> CONN_HIGH_BIT);
- }
-
- private static int getLowWater(final long value) {
- return (int) ((value & CONN_LOW_MASK) >> CONN_LOW_BIT);
- }
-
- public NioSocketStreamConnection accept() throws IOException {
- final WorkerThread current = WorkerThread.getCurrent();
- if (current == null) {
- return null;
- }
- final BlockingQueue<SocketChannel> socketChannels = acceptQueues.get(current.getNumber());
- final SocketChannel accepted;
- boolean ok = false;
- try {
- accepted = socketChannels.poll();
- if (accepted != null) try {
- final SelectionKey selectionKey = current.registerChannel(accepted);
- final NioSocketStreamConnection newConnection = new NioSocketStreamConnection(current, selectionKey, handle);
- newConnection.setOption(Options.READ_TIMEOUT, Integer.valueOf(readTimeout));
- newConnection.setOption(Options.WRITE_TIMEOUT, Integer.valueOf(writeTimeout));
- ok = true;
- return newConnection;
- } finally {
- if (! ok) {
- safeClose(accepted);
- handle.freeConnection();
- }
- }
- } catch (IOException e) {
- return null;
- }
- // by contract, only a resume will do
- return null;
- }
-
- public String toString() {
- return String.format("TCP server (NIO) <%s>", Integer.toHexString(hashCode()));
- }
-
- public ChannelListener<? super QueuedNioTcpServer> getAcceptListener() {
- return acceptListener;
- }
-
- public void setAcceptListener(final ChannelListener<? super QueuedNioTcpServer> acceptListener) {
- this.acceptListener = acceptListener;
- }
-
- public ChannelListener.Setter<QueuedNioTcpServer> getAcceptSetter() {
- return new Setter<QueuedNioTcpServer>(this);
- }
-
- public boolean isOpen() {
- return channel.isOpen();
- }
-
- public SocketAddress getLocalAddress() {
- return socket.getLocalSocketAddress();
- }
-
- public <A extends SocketAddress> A getLocalAddress(final Class<A> type) {
- final SocketAddress address = getLocalAddress();
- return type.isInstance(address) ? type.cast(address) : null;
- }
-
- public void suspendAccepts() {
- synchronized (this) {
- handle.suspend(SelectionKey.OP_ACCEPT);
- suspended = true;
- }
- }
-
- public void resumeAccepts() {
- synchronized (this) {
- suspended = false;
- handle.resume(SelectionKey.OP_ACCEPT);
- }
- }
-
- public boolean isAcceptResumed() {
- return !suspended;
- }
-
- public void wakeupAccepts() {
- tcpServerLog.logf(FQCN, Logger.Level.TRACE, null, "Wake up accepts on %s", this);
- resumeAccepts();
- handle.wakeup(SelectionKey.OP_ACCEPT);
- }
-
- public void awaitAcceptable() throws IOException {
- throw log.unsupported("awaitAcceptable");
- }
-
- public void awaitAcceptable(final long time, final TimeUnit timeUnit) throws IOException {
- throw log.unsupported("awaitAcceptable");
- }
-
- @Deprecated
- public XnioExecutor getAcceptThread() {
- return getIoThread();
- }
-
- void handleReady() {
- final SocketChannel accepted;
- try {
- accepted = channel.accept();
- if(suspendedDueToWatermark) {
- tcpServerConnectionLimitLog.logf(FQCN, Logger.Level.DEBUG, null, "Exceeding connection high water limit (%s). Closing this new accepting request %s", getHighWater(connectionStatus), accepted);
- IoUtils.safeClose(accepted);
- return;
- }
- } catch (ClosedChannelException e) {
- tcpServerLog.logf(FQCN, Logger.Level.DEBUG, e, "ClosedChannelException occurred at accepting request on the server channel %s", channel);
- return;
- } catch (IOException e) {
- tcpServerLog.logf(FQCN, Logger.Level.ERROR, e, "Exception accepting request, closing server channel %s", this);
- IoUtils.safeClose(channel);
- return;
- }
- try {
- boolean ok = false;
- if (accepted != null) try {
- int hash = ThreadLocalRandom.current().nextInt();
- accepted.configureBlocking(false);
- final Socket socket = accepted.socket();
- socket.setKeepAlive(keepAlive != 0);
- socket.setOOBInline(oobInline != 0);
- socket.setTcpNoDelay(tcpNoDelay != 0);
- final int sendBuffer = this.sendBuffer;
- if (sendBuffer > 0) socket.setSendBufferSize(sendBuffer);
- final WorkerThread ioThread = worker.getIoThread(hash);
- ok = true;
- final int number = ioThread.getNumber();
- final BlockingQueue<SocketChannel> queue = acceptQueues.get(number);
- queue.add(accepted);
- // todo: only execute if necessary
- ioThread.execute(acceptTask);
- openConnections++;
- if(openConnections >= getHighWater(connectionStatus)) {
- synchronized (QueuedNioTcpServer.this) {
- suspendedDueToWatermark = true;
- if (limitwarn) {
- tcpServerConnectionLimitLog.logf(FQCN, Logger.Level.WARN, null, "Total open connections reach high water limit (%s) by this new accepting request %s", getHighWater(connectionStatus), accepted);
- limitwarn = false;
- } else {
- tcpServerConnectionLimitLog.logf(FQCN, Logger.Level.DEBUG, null, "Total open connections reach high water limit (%s) by this new accepting request %s", getHighWater(connectionStatus), accepted);
- }
- }
- }
- } finally {
- if (! ok) safeClose(accepted);
- }
- } catch (IOException ignored) {
- }
- }
-
- public void connectionClosed() {
- thread.execute(connectionClosedTask);
- }
-}
=====================================
nio-impl/src/main/java/org/xnio/nio/QueuedNioTcpServerHandle.java → nio-impl/src/test/java/org/xnio/nio/test/AbstractNioSslBufferExpansionTcpTest.java
=====================================
@@ -1,7 +1,7 @@
/*
* JBoss, Home of Professional Open Source
*
- * Copyright 2015 Red Hat, Inc. and/or its affiliates.
+ * Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,46 +15,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.xnio.nio.test;
-package org.xnio.nio;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
-import static org.xnio.IoUtils.safeClose;
-
-import java.nio.channels.SelectionKey;
+import org.xnio.ChannelListener;
+import org.xnio.XnioWorker;
+import org.xnio.channels.AcceptingChannel;
+import org.xnio.channels.ConnectedChannel;
+import org.xnio.channels.StreamSinkChannel;
+import org.xnio.channels.StreamSourceChannel;
/**
- * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ * Superclass for ssl tcp test cases to verify if
+ * {@link javax.net.ssl.SSLEngineResult.Status#BUFFER_OVERFLOW}
+ * is handled appropriately.
+ *
+ * @author <a href="mailto:frainone at redhat.com">Flavia Rainone</a>
+ *
*/
-final class QueuedNioTcpServerHandle extends NioHandle implements ChannelClosed {
-
- private final QueuedNioTcpServer server;
-
- QueuedNioTcpServerHandle(final QueuedNioTcpServer server, final WorkerThread workerThread, final SelectionKey key, final int highWater, final int lowWater) {
- super(workerThread, key);
- this.server = server;
- }
-
- void handleReady(final int ops) {
- server.handleReady();
- }
-
- void forceTermination() {
- safeClose(server);
- }
-
- void terminated() {
- server.invokeCloseHandler();
- }
-
- public void channelClosed() {
- freeConnection();
- }
-
- void freeConnection() {
- server.connectionClosed();
- }
-
- int getConnectionCount() {
- return -1;
+public abstract class AbstractNioSslBufferExpansionTcpTest<T extends ConnectedChannel, R extends StreamSourceChannel, W extends StreamSinkChannel> extends AbstractNioSslTcpTest<T, R, W> {
+
+ @Override
+ protected AcceptingChannel<? extends T> startServer(XnioWorker worker, final ChannelListener<? super T> serverHandler) throws
+ IOException {
+ AcceptingChannel<? extends T> server = super.startServer(worker, serverHandler);
+ // server attack
+ Socket socket = new Socket("127.0.0.1", SERVER_PORT);
+ OutputStream outputStream = socket.getOutputStream();
+ outputStream.write(new byte[]{0x16, 0x3, 0x3, 0x71, 0x41}, 0, 5);
+ return server;
}
}
=====================================
nio-impl/src/test/java/org/xnio/nio/test/AbstractNioTcpTest.java
=====================================
@@ -26,6 +26,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -88,13 +89,7 @@ public abstract class AbstractNioTcpTest<T extends ConnectedChannel, R extends S
worker = xnio.createWorker(OptionMap.create(Options.WORKER_IO_THREADS, threads));
}
try {
- final AcceptingChannel<? extends T> server = createServer(worker,
- new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT),
- ChannelListeners.<T>openListenerAdapter(new CatchingChannelListener<T>(
- serverHandler,
- problems
- )), serverOptionMap);
- server.resumeAccepts();
+ final AcceptingChannel<? extends T> server = startServer(worker, serverHandler);
try {
final IoFuture<? extends T> ioFuture = connect(worker, new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), new CatchingChannelListener<T>(clientHandler, problems), null, clientOptionMap);
final T channel = ioFuture.get();
@@ -120,6 +115,18 @@ public abstract class AbstractNioTcpTest<T extends ConnectedChannel, R extends S
}
}
+ protected AcceptingChannel<? extends T> startServer(XnioWorker worker, final ChannelListener<? super T> serverHandler) throws
+ IOException {
+ final AcceptingChannel<? extends T> server = createServer(worker,
+ new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT),
+ ChannelListeners.<T>openListenerAdapter(new CatchingChannelListener<T>(
+ serverHandler,
+ problems
+ )), serverOptionMap);
+ server.resumeAccepts();
+ return server;
+ }
+
/**
* Set the number of threads that will be used by this test.
*
=====================================
nio-impl/src/test/java/org/xnio/nio/test/NioSslBufferExpansionTcpChannelTestCase.java
=====================================
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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.xnio.nio.test;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.URL;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.xnio.ChannelListener;
+import org.xnio.IoFuture;
+import org.xnio.OptionMap;
+import org.xnio.Xnio;
+import org.xnio.XnioWorker;
+import org.xnio.channels.AcceptingChannel;
+import org.xnio.channels.BoundChannel;
+import org.xnio.channels.ConnectedSslStreamChannel;
+import org.xnio.ssl.XnioSsl;
+
+/**
+ * Test for {@code XnioSsl} channels with a
+ * {@link javax.net.ssl.SSLEngineResult.Status#BUFFER_OVERFLOW} wrap result.
+ *
+ * @author <a href="mailto:frainone at redhat.com">Flavia Rainone</a>
+ *
+ */
+public class NioSslBufferExpansionTcpChannelTestCase extends
+ AbstractNioSslBufferExpansionTcpTest<ConnectedSslStreamChannel, ConnectedSslStreamChannel, ConnectedSslStreamChannel> {
+
+ private XnioSsl xnioSsl;
+ private static final String KEY_STORE_PROPERTY = "javax.net.ssl.keyStore";
+ private static final String KEY_STORE_PASSWORD_PROPERTY = "javax.net.ssl.keyStorePassword";
+ private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";
+ private static final String TRUST_STORE_PASSWORD_PROPERTY = "javax.net.ssl.trustStorePassword";
+ private static final String DEFAULT_KEY_STORE = "keystore.jks";
+ private static final String DEFAULT_KEY_STORE_PASSWORD = "jboss-remoting-test";
+
+ @BeforeClass
+ public static void setKeyStoreAndTrustStore() {
+ final URL storePath = NioSslBufferExpansionTcpChannelTestCase.class.getClassLoader().getResource(DEFAULT_KEY_STORE);
+ if (System.getProperty(KEY_STORE_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(KEY_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ if (System.getProperty(TRUST_STORE_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(TRUST_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected AcceptingChannel<? extends ConnectedSslStreamChannel> createServer(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<AcceptingChannel<ConnectedSslStreamChannel>> openListener, OptionMap optionMap) throws IOException {
+ return xnioSsl.createSslTcpServer(worker, address, openListener, optionMap);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected IoFuture<? extends ConnectedSslStreamChannel> connect(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<ConnectedSslStreamChannel> openListener, ChannelListener<? super BoundChannel> bindListener,
+ OptionMap optionMap) {
+ return xnioSsl.connectSsl(worker, address, openListener, bindListener, optionMap);
+ }
+
+ @Override
+ protected void setReadListener(ConnectedSslStreamChannel channel, ChannelListener<ConnectedSslStreamChannel> readListener) {
+ channel.getReadSetter().set(readListener);
+ }
+
+ @Override
+ protected void setWriteListener(ConnectedSslStreamChannel channel, ChannelListener<ConnectedSslStreamChannel> writeListener) {
+ channel.getWriteSetter().set(writeListener);
+ }
+
+ @Override
+ protected void resumeReads(ConnectedSslStreamChannel channel) {
+ channel.resumeReads();
+ }
+
+ @Override
+ protected void resumeWrites(ConnectedSslStreamChannel channel) {
+ channel.resumeWrites();
+ }
+
+ @Override
+ protected void shutdownReads(ConnectedSslStreamChannel channel) throws IOException {
+ channel.shutdownReads();
+ }
+
+ @Override
+ protected void shutdownWrites(ConnectedSslStreamChannel channel) throws IOException {
+ channel.shutdownWrites();
+ }
+
+ @Override
+ protected void doConnectionTest(final Runnable body, final ChannelListener<? super ConnectedSslStreamChannel> clientHandler, final ChannelListener<? super ConnectedSslStreamChannel> serverHandler) throws Exception {
+ xnioSsl = Xnio.getInstance("nio", NioSslBufferExpansionTcpChannelTestCase.class.getClassLoader()).getSslProvider(OptionMap.EMPTY);
+ super.doConnectionTest(body, clientHandler, serverHandler);
+ }
+}
=====================================
nio-impl/src/test/java/org/xnio/nio/test/NioSslBufferExpansionTcpConnectionTestCase.java
=====================================
@@ -0,0 +1,119 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2020 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed 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.xnio.nio.test;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.URL;
+
+import org.junit.BeforeClass;
+import org.xnio.ChannelListener;
+import org.xnio.IoFuture;
+import org.xnio.OptionMap;
+import org.xnio.Xnio;
+import org.xnio.XnioWorker;
+import org.xnio.channels.AcceptingChannel;
+import org.xnio.channels.BoundChannel;
+import org.xnio.conduits.ConduitStreamSinkChannel;
+import org.xnio.conduits.ConduitStreamSourceChannel;
+import org.xnio.ssl.SslConnection;
+import org.xnio.ssl.XnioSsl;
+
+/**
+ * Test for {@code XnioSsl} connections with a
+ * {@link javax.net.ssl.SSLEngineResult.Status#BUFFER_OVERFLOW} wrap result.
+ *
+ * @author <a href="mailto:frainone at redhat.com">Flavia Rainone</a>
+ *
+ */
+public class NioSslBufferExpansionTcpConnectionTestCase extends
+ AbstractNioSslBufferExpansionTcpTest<SslConnection, ConduitStreamSourceChannel, ConduitStreamSinkChannel> {
+ private XnioSsl xnioSsl;
+ private static final String KEY_STORE_PROPERTY = "javax.net.ssl.keyStore";
+ private static final String KEY_STORE_PASSWORD_PROPERTY = "javax.net.ssl.keyStorePassword";
+ private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";
+ private static final String TRUST_STORE_PASSWORD_PROPERTY = "javax.net.ssl.trustStorePassword";
+ private static final String DEFAULT_KEY_STORE = "keystore.jks";
+ private static final String DEFAULT_KEY_STORE_PASSWORD = "jboss-remoting-test";
+
+ @BeforeClass
+ public static void setKeyStoreAndTrustStore() {
+ final URL storePath = NioSslTcpChannelTestCase.class.getClassLoader().getResource(DEFAULT_KEY_STORE);
+ if (System.getProperty(KEY_STORE_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(KEY_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ if (System.getProperty(TRUST_STORE_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(TRUST_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ }
+
+ @Override
+ protected AcceptingChannel<? extends SslConnection> createServer(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<AcceptingChannel<SslConnection>> openListener, OptionMap optionMap) throws IOException {
+ return xnioSsl.createSslConnectionServer(worker, address, openListener, optionMap);
+ }
+
+ @Override
+ protected IoFuture<? extends SslConnection> connect(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<SslConnection> openListener, ChannelListener<? super BoundChannel> bindListener,
+ OptionMap optionMap) {
+ return xnioSsl.openSslConnection(worker, address, openListener, bindListener, optionMap);
+ }
+
+ @Override
+ protected void setReadListener(SslConnection connection, ChannelListener<ConduitStreamSourceChannel> readListener) {
+ connection.getSourceChannel().setReadListener(readListener);
+ }
+
+ @Override
+ protected void setWriteListener(SslConnection connection, ChannelListener<ConduitStreamSinkChannel> writeListener) {
+ connection.getSinkChannel().setWriteListener(writeListener);
+ }
+
+ @Override
+ protected void resumeReads(SslConnection connection) {
+ connection.getSourceChannel().resumeReads();
+ }
+
+ @Override
+ protected void resumeWrites(SslConnection connection) {
+ connection.getSinkChannel().resumeWrites();
+ }
+
+ @Override
+ protected void shutdownReads(SslConnection connection) throws IOException {
+ connection.getSourceChannel().shutdownReads();
+ }
+
+ @Override
+ protected void shutdownWrites(SslConnection connection) throws IOException {
+ connection.getSinkChannel().shutdownWrites();
+ }
+
+ @Override
+ protected void doConnectionTest(final Runnable body, final ChannelListener<? super SslConnection> clientHandler, final ChannelListener<? super SslConnection> serverHandler) throws Exception {
+ xnioSsl = Xnio.getInstance("nio", NioSslTcpChannelTestCase.class.getClassLoader()).getSslProvider(OptionMap.EMPTY);
+ super.doConnectionTest(body, clientHandler, serverHandler);
+ }
+}
=====================================
nio-impl/src/test/java/org/xnio/nio/test/NioSslRandomlyTimedBufferExpansionTcpChannelTestCase.java
=====================================
@@ -0,0 +1,141 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2020 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed 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.xnio.nio.test;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.URL;
+
+import org.junit.BeforeClass;
+import org.xnio.ChannelListener;
+import org.xnio.IoFuture;
+import org.xnio.OptionMap;
+import org.xnio.Xnio;
+import org.xnio.XnioWorker;
+import org.xnio.channels.AcceptingChannel;
+import org.xnio.channels.BoundChannel;
+import org.xnio.channels.ConnectedSslStreamChannel;
+import org.xnio.ssl.XnioSsl;
+
+/**
+ * Test for {@code XnioSsl} channel with a
+ * {@link javax.net.ssl.SSLEngineResult.Status#BUFFER_OVERFLOW} result
+ * presented at a random time.
+ *
+ * @author <a href="mailto:frainone at redhat.com">Flavia Rainone</a>
+ *
+ */
+public class NioSslRandomlyTimedBufferExpansionTcpChannelTestCase extends AbstractNioSslTcpTest<ConnectedSslStreamChannel, ConnectedSslStreamChannel, ConnectedSslStreamChannel>{
+ private XnioSsl xnioSsl;
+ private static final String KEY_STORE_PROPERTY = "javax.net.ssl.keyStore";
+ private static final String KEY_STORE_PASSWORD_PROPERTY = "javax.net.ssl.keyStorePassword";
+ private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";
+ private static final String TRUST_STORE_PASSWORD_PROPERTY = "javax.net.ssl.trustStorePassword";
+ private static final String DEFAULT_KEY_STORE = "keystore.jks";
+ private static final String DEFAULT_KEY_STORE_PASSWORD = "jboss-remoting-test";
+
+ @Override
+ protected AcceptingChannel<? extends ConnectedSslStreamChannel> startServer(XnioWorker worker, final ChannelListener<? super ConnectedSslStreamChannel> serverHandler) throws
+ IOException {
+ AcceptingChannel<? extends ConnectedSslStreamChannel> server = super.startServer(worker, serverHandler);
+ // server atack
+ Thread thread = new Thread(() -> {
+ final Socket socket;
+ try {
+ Thread.sleep((long) (Math.random()*300));
+ socket = new Socket("127.0.0.1", SERVER_PORT);
+ OutputStream outputStream = socket.getOutputStream();
+ outputStream.write(new byte[]{0x16, 0x3, 0x3, 0x71, 0x41}, 0, 5);
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ }});
+ thread.start();
+
+ return server;
+ }
+
+ @BeforeClass
+ public static void setKeyStoreAndTrustStore() {
+ final URL storePath = NioSslTcpChannelTestCase.class.getClassLoader().getResource(DEFAULT_KEY_STORE);
+ if (System.getProperty(KEY_STORE_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(KEY_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ if (System.getProperty(TRUST_STORE_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(TRUST_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected AcceptingChannel<? extends ConnectedSslStreamChannel> createServer(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<AcceptingChannel<ConnectedSslStreamChannel>> openListener, OptionMap optionMap) throws IOException {
+ return xnioSsl.createSslTcpServer(worker, address, openListener, optionMap);
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected IoFuture<? extends ConnectedSslStreamChannel> connect(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<ConnectedSslStreamChannel> openListener, ChannelListener<? super BoundChannel> bindListener,
+ OptionMap optionMap) {
+ return xnioSsl.connectSsl(worker, address, openListener, bindListener, optionMap);
+ }
+
+ @Override
+ protected void setReadListener(ConnectedSslStreamChannel channel, ChannelListener<ConnectedSslStreamChannel> readListener) {
+ channel.getReadSetter().set(readListener);
+ }
+
+ @Override
+ protected void setWriteListener(ConnectedSslStreamChannel channel, ChannelListener<ConnectedSslStreamChannel> writeListener) {
+ channel.getWriteSetter().set(writeListener);
+ }
+
+ @Override
+ protected void resumeReads(ConnectedSslStreamChannel channel) {
+ channel.resumeReads();
+ }
+
+ @Override
+ protected void resumeWrites(ConnectedSslStreamChannel channel) {
+ channel.resumeWrites();
+ }
+
+ @Override
+ protected void shutdownReads(ConnectedSslStreamChannel channel) throws IOException {
+ channel.shutdownReads();
+ }
+
+ @Override
+ protected void shutdownWrites(ConnectedSslStreamChannel channel) throws IOException {
+ channel.shutdownWrites();
+ }
+
+ @Override
+ protected void doConnectionTest(final Runnable body, final ChannelListener<? super ConnectedSslStreamChannel> clientHandler, final ChannelListener<? super ConnectedSslStreamChannel> serverHandler) throws Exception {
+ xnioSsl = Xnio.getInstance("nio", NioSslTcpChannelTestCase.class.getClassLoader()).getSslProvider(OptionMap.EMPTY);
+ super.doConnectionTest(body, clientHandler, serverHandler);
+ }
+}
=====================================
nio-impl/src/test/java/org/xnio/nio/test/NioSslRandomlyTimedBufferExpansionTcpConnectionTestCase.java
=====================================
@@ -0,0 +1,141 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2020 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed 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.xnio.nio.test;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.URL;
+
+import org.junit.BeforeClass;
+import org.xnio.ChannelListener;
+import org.xnio.IoFuture;
+import org.xnio.OptionMap;
+import org.xnio.Xnio;
+import org.xnio.XnioWorker;
+import org.xnio.channels.AcceptingChannel;
+import org.xnio.channels.BoundChannel;
+import org.xnio.conduits.ConduitStreamSinkChannel;
+import org.xnio.conduits.ConduitStreamSourceChannel;
+import org.xnio.ssl.SslConnection;
+import org.xnio.ssl.XnioSsl;
+
+/**
+ * Test for {@code XnioSsl} connection with a
+ * {@link javax.net.ssl.SSLEngineResult.Status#BUFFER_OVERFLOW} result
+ * presented at a random time.
+ *
+ * @author <a href="mailto:frainone at redhat.com">Flavia Rainone</a>
+ *
+ */
+public class NioSslRandomlyTimedBufferExpansionTcpConnectionTestCase extends AbstractNioSslTcpTest<SslConnection, ConduitStreamSourceChannel, ConduitStreamSinkChannel>{
+ private XnioSsl xnioSsl;
+ private static final String KEY_STORE_PROPERTY = "javax.net.ssl.keyStore";
+ private static final String KEY_STORE_PASSWORD_PROPERTY = "javax.net.ssl.keyStorePassword";
+ private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";
+ private static final String TRUST_STORE_PASSWORD_PROPERTY = "javax.net.ssl.trustStorePassword";
+ private static final String DEFAULT_KEY_STORE = "keystore.jks";
+ private static final String DEFAULT_KEY_STORE_PASSWORD = "jboss-remoting-test";
+
+ @Override
+ protected AcceptingChannel<? extends SslConnection> startServer(XnioWorker worker, final ChannelListener<? super SslConnection> serverHandler) throws
+ IOException {
+ AcceptingChannel<? extends SslConnection> server = super.startServer(worker, serverHandler);
+ // server atack
+ Thread thread = new Thread(() -> {
+ final Socket socket;
+ try {
+ Thread.sleep((long) (Math.random()*300));
+ socket = new Socket("127.0.0.1", SERVER_PORT);
+ OutputStream outputStream = socket.getOutputStream();
+ outputStream.write(new byte[]{0x16, 0x3, 0x3, 0x71, 0x41}, 0, 5);
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ }});
+ thread.start();
+
+ return server;
+ }
+
+ @BeforeClass
+ public static void setKeyStoreAndTrustStore() {
+ final URL storePath = NioSslTcpChannelTestCase.class.getClassLoader().getResource(DEFAULT_KEY_STORE);
+ if (System.getProperty(KEY_STORE_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(KEY_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(KEY_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ if (System.getProperty(TRUST_STORE_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PROPERTY, storePath.getFile());
+ }
+ if (System.getProperty(TRUST_STORE_PASSWORD_PROPERTY) == null) {
+ System.setProperty(TRUST_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD);
+ }
+ }
+
+ @Override
+ protected AcceptingChannel<? extends SslConnection> createServer(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<AcceptingChannel<SslConnection>> openListener, OptionMap optionMap) throws IOException {
+ return xnioSsl.createSslConnectionServer(worker, address, openListener, optionMap);
+ }
+
+ @Override
+ protected IoFuture<? extends SslConnection> connect(XnioWorker worker, InetSocketAddress address,
+ ChannelListener<SslConnection> openListener, ChannelListener<? super BoundChannel> bindListener,
+ OptionMap optionMap) {
+ return xnioSsl.openSslConnection(worker, address, openListener, bindListener, optionMap);
+ }
+
+ @Override
+ protected void setReadListener(SslConnection connection, ChannelListener<ConduitStreamSourceChannel> readListener) {
+ connection.getSourceChannel().setReadListener(readListener);
+ }
+
+ @Override
+ protected void setWriteListener(SslConnection connection, ChannelListener<ConduitStreamSinkChannel> writeListener) {
+ connection.getSinkChannel().setWriteListener(writeListener);
+ }
+
+ @Override
+ protected void resumeReads(SslConnection connection) {
+ connection.getSourceChannel().resumeReads();
+ }
+
+ @Override
+ protected void resumeWrites(SslConnection connection) {
+ connection.getSinkChannel().resumeWrites();
+ }
+
+ @Override
+ protected void shutdownReads(SslConnection connection) throws IOException {
+ connection.getSourceChannel().shutdownReads();
+ }
+
+ @Override
+ protected void shutdownWrites(SslConnection connection) throws IOException {
+ connection.getSinkChannel().shutdownWrites();
+ }
+
+ @Override
+ protected void doConnectionTest(final Runnable body, final ChannelListener<? super SslConnection> clientHandler, final ChannelListener<? super SslConnection> serverHandler) throws Exception {
+ xnioSsl = Xnio.getInstance("nio", NioSslTcpChannelTestCase.class.getClassLoader()).getSslProvider(OptionMap.EMPTY);
+ super.doConnectionTest(body, clientHandler, serverHandler);
+ }
+}
=====================================
pom.xml
=====================================
@@ -32,7 +32,7 @@
<artifactId>xnio-all</artifactId>
<packaging>pom</packaging>
<name>XNIO Parent POM</name>
- <version>3.7.7.Final</version>
+ <version>3.8.0.Final</version>
<description>The aggregator POM of the XNIO project</description>
<licenses>
@@ -49,16 +49,16 @@
</modules>
<properties>
- <byteman-version>4.0.6</byteman-version>
- <version.org.jboss.logging.jboss-logging>3.4.0.Final</version.org.jboss.logging.jboss-logging>
- <version.org.jboss.logging.jboss-logging-tools>2.2.0.Final</version.org.jboss.logging.jboss-logging-tools>
- <version.org.jboss.logmanager.jboss-logmanager>2.1.10.Final</version.org.jboss.logmanager.jboss-logmanager>
- <version.org.jboss.threads>2.3.0.Beta2</version.org.jboss.threads>
+ <byteman-version>4.0.8</byteman-version>
+ <version.org.jboss.logging.jboss-logging>3.4.1.Final</version.org.jboss.logging.jboss-logging>
+ <version.org.jboss.logging.jboss-logging-tools>2.2.1.Final</version.org.jboss.logging.jboss-logging-tools>
+ <version.org.jboss.logmanager.jboss-logmanager>2.1.14.Final</version.org.jboss.logmanager.jboss-logmanager>
+ <version.org.jboss.threads>2.3.3.Final</version.org.jboss.threads>
<version.org.wildfly.common>1.5.2.Final</version.org.wildfly.common>
- <version.org.wildfly.client-config>1.0.0.Final</version.org.wildfly.client-config>
- <version.bridger.plugin>1.1.Final</version.bridger.plugin>
- <version.junit>4.11</version.junit>
- <version.jmock>2.6.0</version.jmock>
+ <version.org.wildfly.client-config>1.0.1.Final</version.org.wildfly.client-config>
+ <version.bridger.plugin>1.5.Final</version.bridger.plugin>
+ <version.junit>4.12</version.junit>
+ <version.jmock>2.12.0</version.jmock>
<org.xnio.ssl.new>false</org.xnio.ssl.new>
<version.org.osgi.core>6.0.0</version.org.osgi.core>
View it on GitLab: https://salsa.debian.org/java-team/jboss-xnio/-/compare/b99bec6524f8564641c46a43a3fedac5ce2a24fe...afe9826d3e3997a7f4e9b2032a9a2e262be1884b
--
View it on GitLab: https://salsa.debian.org/java-team/jboss-xnio/-/compare/b99bec6524f8564641c46a43a3fedac5ce2a24fe...afe9826d3e3997a7f4e9b2032a9a2e262be1884b
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20200327/adb1bbee/attachment.html>
More information about the pkg-java-commits
mailing list