From f48d175e8397ca097f87952bdef8349481975ad0 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Sat, 16 Feb 2013 09:38:14 -0500 Subject: [PATCH] INT-2936 Fix TCP Binary DeSerialization with NIO Inadvertent sign extension on binary data with bit 7 set causes early termination of binary deserializers. The ChannelInputStream (which replaced the piped input and output streams) failed to mask off the top 24 bits of "normal" bytes received, causing Deserializers to believe the stream was closed. Add a mask of 0xff to bytes read. Add a test case. --- .../ip/tcp/connection/TcpNioConnection.java | 4 ++-- .../ip/tcp/connection/TcpNetConnectionTests.java | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioConnection.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioConnection.java index b2e0bcf6f3..b368a70742 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioConnection.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioConnection.java @@ -69,7 +69,7 @@ public class TcpNioConnection extends TcpConnectionSupport { private volatile long lastSend; - private AtomicInteger executionControl = new AtomicInteger(); + private final AtomicInteger executionControl = new AtomicInteger(); private volatile boolean writingToPipe; @@ -560,7 +560,7 @@ public class TcpNioConnection extends TcpConnectionSupport { } } int bite; - bite = this.currentBuffer[this.currentOffset++]; + bite = this.currentBuffer[this.currentOffset++] & 0xff; this.available.decrementAndGet(); if (this.currentOffset >= this.currentBuffer.length) { this.currentBuffer = null; diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java index 83a93e8d26..e768b2ed98 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import java.io.InputStream; import java.net.Socket; +import java.nio.channels.SocketChannel; import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.logging.Log; @@ -31,7 +32,9 @@ import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.beans.DirectFieldAccessor; +import org.springframework.integration.ip.tcp.connection.TcpNioConnection.ChannelInputStream; import org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer; +import org.springframework.integration.test.util.TestUtils; /** * @author Gary Russell @@ -68,4 +71,15 @@ public class TcpNetConnectionTests { log.get()); } + @Test + public void testBinary() throws Exception { + SocketChannel socketChannel = mock(SocketChannel.class); + Socket socket = mock(Socket.class); + when(socketChannel.socket()).thenReturn(socket); + TcpNioConnection connection = new TcpNioConnection(socketChannel, true, false, null, null); + ChannelInputStream inputStream = TestUtils.getPropertyValue(connection, "channelInputStream", ChannelInputStream.class); + inputStream.write(new byte[] {(byte) 0x80}, 1); + assertEquals(0x80, inputStream.read()); + } + }